diff options
Diffstat (limited to 'qemu/roms/openhackware/src/libc')
-rw-r--r-- | qemu/roms/openhackware/src/libc/include/ctype.h | 113 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/include/endian.h | 514 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/include/errno.h | 62 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/include/fcntl.h | 33 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/include/stddef.h | 38 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/include/stdint.h | 74 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/include/stdio.h | 43 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/include/stdlib.h | 50 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/include/string.h | 90 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/include/strings.h | 27 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/include/unistd.h | 43 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/src/errno.c | 25 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/src/format.c | 467 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/src/malloc.c | 730 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/src/mem.c | 251 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libc/src/str.c | 430 |
16 files changed, 2990 insertions, 0 deletions
diff --git a/qemu/roms/openhackware/src/libc/include/ctype.h b/qemu/roms/openhackware/src/libc/include/ctype.h new file mode 100644 index 000000000..09309c163 --- /dev/null +++ b/qemu/roms/openhackware/src/libc/include/ctype.h @@ -0,0 +1,113 @@ +/* + * <ctype.h> + * + * Open Hack'Ware BIOS POSIX like ctype definitions + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined (__OHW_CTYPE_H__) +#define __OHW_CTYPE_H__ + +/* Beware that those routines only support ASCII */ +static inline int islower (int c) +{ + return c >= 'a' && c <= 'z'; +} + +static inline int isupper (int c) +{ + return c >= 'A' && c <= 'Z'; +} + +static inline int isalpha (int c) +{ + return islower(c) || isupper(c); +} + +static inline int isdigit (int c) +{ + return c >= '0' && c <= '9'; +} + +static inline int isalnum (int c) +{ + return isalpha(c) || isdigit(c); +} + +static inline int isxdigit (int c) +{ + return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); +} + +static inline int isspace (int c) +{ + return c == ' ' || c == '\f' || c == '\n' || c == '\r' || + c == '\t' || c == '\v'; +} + +static inline int isgraph (int c) +{ + return (c >= 0x21 && c <= 0x7E) || (c >= 0xA1 && c <= 0xFF); +} + +static inline int isprint (int c) +{ + return isgraph(c) && c != ' '; +} + +static inline int ispunct (int c) +{ + return isprint(c) && !isalpha(c) && !isspace(c); +} + +static inline int isblank (int c) +{ + return c == ' ' || c == '\t'; +} + +static inline int iscntrl (int c) +{ + return !isprint(c); +} + +static inline int isascii (int c) +{ + return (c & 0x80) == 0; +} + +static inline int tolower (int c) +{ + if (isupper(c)) + c |= 0x20; + + return c; +} + +static inline int toupper (int c) +{ + if (islower(c)) + c &= ~0x20; + + return c; +} + +static inline int toascii (int c) +{ + return c & ~0x80; +} + +#endif /* !defined (__OHW_CTYPE_H__) */ diff --git a/qemu/roms/openhackware/src/libc/include/endian.h b/qemu/roms/openhackware/src/libc/include/endian.h new file mode 100644 index 000000000..d0ec79712 --- /dev/null +++ b/qemu/roms/openhackware/src/libc/include/endian.h @@ -0,0 +1,514 @@ +/* + * <endian.h> + * + * Open Hack'Ware BIOS: provides all common endianness conversions functions + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* + * This file provides: + * void cpu_to_be16p (uint16_t *outp, uint16_t in); + * void cpu_to_be32p (uint32_t *outp, uint32_t in); + * void cpu_to_be64p (uint64_t *outp, uint64_t in); + * void cpu_to_le16p (uint16_t *outp, uint16_t in); + * void cpu_to_le32p (uint32_t *outp, uint32_t in); + * void cpu_to_le64p (uint64_t *outp, uint64_t in); + * void endian_to_cpu16p (uint16_t *outp, uint16_t in, endian_t endian); + * void endian_to_cpu32p (uint32_t *outp, uint32_t in, endian_t endian); + * void endian_to_cpu64p (uint64_t *outp, uint64_t in, endian_t endian); + * void cpu16_to_endianp (uint16_t *outp, uint16_t in, endian_t endian); + * void cpu32_to_endianp (uint32_t *outp, uint32_t in, endian_t endian); + * void cpu64_to_endianp (uint64_t *outp, uint64_t in, endian_t endian); + * + */ + +#if !defined (__OHW_ENDIAN_H__) +#define __OHW_ENDIAN_H__ + +#include <stdint.h> + +typedef enum endian_t endian_t; +enum endian_t { + ENDIAN_1234 = 0, + ENDIAN_4321, + ENDIAN_3412, + ENDIAN_2143, +}; + +/* Generic endian conversion functions */ +static inline void generic_cpu_swap16p (uint16_t *outp, uint16_t in) +{ + *outp = ((in & 0xFF00) >> 8) | ((in & 0x00FF) << 8); +} + +static inline void generic_cpu_swap32p (uint32_t *outp, uint32_t in) +{ + *outp = ((in & 0xFF000000) >> 24) | ((in & 0x00FF0000) >> 8) | + ((in & 0x0000FF00) << 8) | ((in & 0x000000FF) << 24); +} + +static inline void generic_cpu_swap64p (uint64_t *outp, uint64_t in) +{ + *outp = ((in & 0xFF00000000000000ULL) >> 56) | + ((in & 0x00FF000000000000ULL) >> 40) | + ((in & 0x0000FF0000000000ULL) >> 24) | + ((in & 0x000000FF00000000ULL) >> 8) | + ((in & 0x00000000FF000000ULL) << 8) | + ((in & 0x0000000000FF0000ULL) << 24) | + ((in & 0x000000000000FF00ULL) << 40) | + ((in & 0x00000000000000FFULL) << 56); +} + +static inline void generic_cpu_swap64p_32 (uint64_t *outp, uint64_t in) +{ + uint32_t *_outp = (uint32_t *)outp; + + generic_cpu_swap32p(_outp, in); + generic_cpu_swap32p(_outp + 1, in >> 32); +} + +#if defined (__i386__) + +#define __CPU_ENDIAN_4321__ +#define __CPU_LENGTH_32__ + +#elif defined (__x86_64__) + +#define __CPU_ENDIAN_4321__ +#define __CPU_LENGTH_64__ + +#elif defined (__powerpc__) || defined (_ARCH_PPC) + +#define __CPU_ENDIAN_1234__ +#define __CPU_LENGTH_32__ + +#define __HAVE_CPU_SWAP16P__ +static inline void cpu_swap16p (uint16_t *outp, uint16_t in) +{ + __asm__ __volatile__ ("sthbrx %4, 0(%3)"); +} + +#define __HAVE_CPU_SWAP32P__ +static inline void cpu_swap32p (uint32_t *outp, uint32_t in) +{ + __asm__ __volatile__ ("stwbrx %4, 0(%3)"); +} + +#define __HAVE_CPU_SWAP64P__ +static inline void cpu_swap64p (uint64_t *outp, uint64_t in) +{ + return generic_cpu_swap64p_32(outp, in); +} + +#else + +#error "unsupported CPU architecture" + +#endif + +/* Use generic swap function if no cpu specific were provided */ +#if !defined (__HAVE_CPU_SWAP16P__) +static inline void cpu_swap16p (uint16_t *outp, uint16_t in) +{ + generic_cpu_swap16p(outp, in); +} +#endif + +#if !defined (__HAVE_CPU_SWAP32P__) +static inline void cpu_swap32p (uint32_t *outp, uint32_t in) +{ + generic_cpu_swap32p(outp, in); +} +#endif + +#if !defined (__HAVE_CPU_SWAP64P__) +static inline void cpu_swap64p (uint64_t *outp, uint64_t in) +{ +#if defined (__CPU_LENGTH_64__) + generic_cpu_swap64p(outp, in); +#elif defined (__CPU_LENGTH_32__) + generic_cpu_swap64p_32(outp, in); +#else +#error "Don't know how to make 64 bits swapping on this arch" +#endif +} +#endif + +static inline void cpu_nswap16p (uint16_t *outp, uint16_t in) +{ + *outp = in; +} + +static inline void cpu_nswap32p (uint32_t *outp, uint32_t in) +{ + *outp = in; +} + +static inline void cpu_nswap64p (uint64_t *outp, uint64_t in) +{ + *outp = in; +} + +static inline void _endian_be16_p (uint16_t *outp, uint16_t in, + endian_t endian) +{ + switch (endian) { + case ENDIAN_4321: + case ENDIAN_2143: + cpu_swap16p(outp, in); + break; + case ENDIAN_1234: + case ENDIAN_3412: + cpu_nswap16p(outp, in); + break; + } +} + +static inline void _endian_be32_p (uint32_t *outp, uint32_t in, + endian_t endian) +{ + switch (endian) { + case ENDIAN_4321: + cpu_swap32p(outp, in); + break; + case ENDIAN_1234: + cpu_nswap32p(outp, in); + break; + case ENDIAN_2143: + /* TODO */ + break; + case ENDIAN_3412: + /* TODO */ + break; + } +} + +static inline void _endian_be64_p (uint64_t *outp, uint64_t in, + endian_t endian) +{ + switch (endian) { + case ENDIAN_4321: + cpu_swap64p(outp, in); + break; + case ENDIAN_1234: + cpu_nswap64p(outp, in); + break; + case ENDIAN_2143: + /* TODO */ + break; + case ENDIAN_3412: + /* TODO */ + break; + } +} + +static inline void _endian_le16_p (uint16_t *outp, uint16_t in, + endian_t endian) +{ + switch (endian) { + case ENDIAN_4321: + case ENDIAN_2143: + cpu_nswap16p(outp, in); + break; + case ENDIAN_1234: + case ENDIAN_3412: + cpu_swap16p(outp, in); + break; + } +} + +static inline void _endian_le32_p (uint32_t *outp, uint32_t in, + endian_t endian) +{ + switch (endian) { + case ENDIAN_4321: + cpu_nswap32p(outp, in); + break; + case ENDIAN_1234: + cpu_swap32p(outp, in); + break; + case ENDIAN_2143: + /* TODO */ + break; + case ENDIAN_3412: + /* TODO */ + break; + } +} + +static inline void _endian_le64_p (uint64_t *outp, uint64_t in, + endian_t endian) +{ + switch (endian) { + case ENDIAN_4321: + cpu_nswap64p(outp, in); + break; + case ENDIAN_1234: + cpu_swap64p(outp, in); + break; + case ENDIAN_2143: + /* TODO */ + break; + case ENDIAN_3412: + /* TODO */ + break; + } +} + +static inline void endian_to_be16p (uint16_t *outp, uint16_t in, + endian_t endian) +{ + _endian_be16_p(outp, in, endian); +} + +static inline void endian_to_be32p (uint32_t *outp, uint32_t in, + endian_t endian) +{ + _endian_be32_p(outp, in, endian); +} + +static inline void endian_to_be64p (uint64_t *outp, uint64_t in, + endian_t endian) +{ + _endian_be64_p(outp, in, endian); +} + +static inline void endian_to_le16p (uint16_t *outp, uint16_t in, + endian_t endian) +{ + _endian_le16_p(outp, in, endian); +} + +static inline void endian_to_le32p (uint32_t *outp, uint32_t in, + endian_t endian) +{ + _endian_le32_p(outp, in, endian); +} + +static inline void endian_to_le64p (uint64_t *outp, uint64_t in, + endian_t endian) +{ + _endian_le64_p(outp, in, endian); +} + +static inline void be16_to_endianp (uint16_t *outp, uint16_t in, + endian_t endian) +{ + _endian_be16_p(outp, in, endian); +} + +static inline void be32_to_endianp (uint32_t *outp, uint32_t in, + endian_t endian) +{ + _endian_be32_p(outp, in, endian); +} + +static inline void be64_to_endianp (uint64_t *outp, uint64_t in, + endian_t endian) +{ + _endian_be64_p(outp, in, endian); +} + +static inline void le16_to_endianp (uint16_t *outp, uint16_t in, + endian_t endian) +{ + _endian_le16_p(outp, in, endian); +} + +static inline void le32_to_endianp (uint32_t *outp, uint32_t in, + endian_t endian) +{ + _endian_le32_p(outp, in, endian); +} + +static inline void le64_to_endianp (uint64_t *outp, uint64_t in, + endian_t endian) +{ + _endian_le64_p(outp, in, endian); +} + +#if defined (__CPU_ENDIAN_4321__) + +static inline void cpu_to_be16p (uint16_t *outp, uint16_t in) +{ + cpu_swap16p(outp, in); +} + +static inline void cpu_to_be32p (uint32_t *outp, uint32_t in) +{ + cpu_swap32p(outp, in); +} + +static inline void cpu_to_be64p (uint64_t *outp, uint64_t in) +{ + cpu_swap64p(outp, in); +} + +static inline void cpu_to_le16p (uint16_t *outp, uint16_t in) +{ + cpu_nswap16p(outp, in); +} + +static inline void cpu_to_le32p (uint32_t *outp, uint32_t in) +{ + cpu_nswap32p(outp, in); +} + +static inline void cpu_to_le64p (uint64_t *outp, uint64_t in) +{ + cpu_nswap64p(outp, in); +} + +static inline void be16_to_cpup (uint16_t *outp, uint16_t in) +{ + cpu_swap16p(outp, in); +} + +static inline void be32_to_cpup (uint32_t *outp, uint32_t in) +{ + cpu_swap32p(outp, in); +} + +static inline void be64_to_cpup (uint64_t *outp, uint64_t in) +{ + cpu_swap64p(outp, in); +} + +static inline void le16_to_cpup (uint16_t *outp, uint16_t in) +{ + cpu_nswap16p(outp, in); +} + +static inline void le32_to_cpup (uint32_t *outp, uint32_t in) +{ + cpu_nswap32p(outp, in); +} + +static inline void le64_to_cpup (uint64_t *outp, uint64_t in) +{ + cpu_nswap64p(outp, in); +} + +static inline void endian_to_cpu16p (uint16_t *outp, uint16_t in, + endian_t endian) +{ + endian_to_le16p(outp, in, endian); +} + +static inline void endian_to_cpu32p (uint32_t *outp, uint32_t in, + endian_t endian) +{ + endian_to_le32p(outp, in, endian); +} + +static inline void endian_to_cpu64p (uint64_t *outp, uint64_t in, + endian_t endian) +{ + endian_to_le64p(outp, in, endian); +} + +static inline void cpu16_to_endianp (uint16_t *outp, uint16_t in, + endian_t endian) +{ + le16_to_endianp(outp, in, endian); +} + +static inline void cpu32_to_endianp (uint32_t *outp, uint32_t in, + endian_t endian) +{ + le32_to_endianp(outp, in, endian); +} + +static inline void cpu64_to_endianp (uint64_t *outp, uint64_t in, + endian_t endian) +{ + le64_to_endianp(outp, in, endian); +} + +#elif defined (__CPU_ENDIAN_1234__) + +static inline void cpu_to_be16p (uint16_t *outp, uint16_t in) +{ + cpu_nswap16p(outp, in); +} + +static inline void cpu_to_be32p (uint32_t *outp, uint32_t in) +{ + cpu_nswap32p(outp, in); +} + +static inline void cpu_to_be64p (uint64_t *outp, uint64_t in) +{ + cpu_nswap64p(outp, in); +} + +static inline void cpu_to_le16p (uint16_t *outp, uint16_t in) +{ + cpu_swap16p(outp, in); +} + +static inline void cpu_to_le32p (uint32_t *outp, uint32_t in) +{ + cpu_swap32p(outp, in); +} + +static inline void cpu_to_le64p (uint64_t *outp, uint64_t in) +{ + cpu_swap64p(outp, in); +} + +static inline void endian_to_cpu16p (uint16_t *outp, uint16_t in, + endian_t endian) +{ + endian_to_be16p(outp, in, endian); +} + +static inline void endian_to_cpu32p (uint32_t *outp, uint32_t in, + endian_t endian) +{ + endian_to_be32p(outp, in, endian); +} + +static inline void endian_to_cpu64p (uint64_t *outp, uint64_t in, + endian_t endian) +{ + endian_to_be64p(outp, in, endian); +} + +static inline void cpu16_to_endianp (uint16_t *outp, uint16_t in, + endian_t endian) +{ + be16_to_endianp(outp, in, endian); +} + +static inline void cpu32_to_endianp (uint32_t *outp, uint32_t in, + endian_t endian) +{ + be32_to_endianp(outp, in, endian); +} + +static inline void cpu64_to_endianp (uint64_t *outp, uint64_t in, + endian_t endian) +{ + be64_to_endianp(outp, in, endian); +} + +#else /* 2143 / 3412 */ +/* TODO */ +#error "TODO" +#endif + +#endif /* !defined (__OHW_ENDIAN_H__) */ diff --git a/qemu/roms/openhackware/src/libc/include/errno.h b/qemu/roms/openhackware/src/libc/include/errno.h new file mode 100644 index 000000000..f6242a581 --- /dev/null +++ b/qemu/roms/openhackware/src/libc/include/errno.h @@ -0,0 +1,62 @@ +/* + * <errno.h> + * + * Open Hack'Ware BIOS errno management + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#if !defined (__OHW_ERRNO_H__) +#define __OHW_ERRNO_H__ + +struct task { + int errno; +}; + +extern struct task cur_task; + +void *get_current_stack (void); + +static inline int *errno_location (void) +{ + /* XXX: to fix */ +#if 0 + struct task *taskp; + + taskp = get_current_stack(); + + return &taskp->errno; +#else + return &cur_task.errno; +#endif +} + +static inline void set_errno (int errnum) +{ + *(errno_location()) = errnum; +} + +static inline int get_errno (void) +{ + return *(errno_location()); +} + +#define errno get_errno() + +enum { + ENOMEM, +}; + +#endif /* !defined (__OHW_ERRNO_H__) */ diff --git a/qemu/roms/openhackware/src/libc/include/fcntl.h b/qemu/roms/openhackware/src/libc/include/fcntl.h new file mode 100644 index 000000000..d55c477b0 --- /dev/null +++ b/qemu/roms/openhackware/src/libc/include/fcntl.h @@ -0,0 +1,33 @@ +/* + * <fcntl.h> + * + * Open Hack'Ware BIOS: subset of POSIX fcntl definitions + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined (__OHW_FCNTL_H__) +#define __OHW_FCNTL_H__ + +enum { + O_RDONLY = 0x0001, + O_WRONLY = 0x0002, + O_RDWR = 0x0003, + O_CREAT = 0x0010, + O_EXCL = 0x0020, +}; + +#endif /* !defined (__OHW_FCNTL_H__) */ diff --git a/qemu/roms/openhackware/src/libc/include/stddef.h b/qemu/roms/openhackware/src/libc/include/stddef.h new file mode 100644 index 000000000..0e973eb15 --- /dev/null +++ b/qemu/roms/openhackware/src/libc/include/stddef.h @@ -0,0 +1,38 @@ +/* + * <stddef.h> + * + * Open Hack'Ware BIOS: subset of POSIX standard definitions + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined (__OHW_STDDEF_H__) +#define __OHW_STDDEF_H__ + +#include <stdint.h> + +typedef signed long ptrdiff_t; +typedef unsigned long size_t; +typedef signed long ssize_t; +typedef signed long off_t; + +/* We use unicode UCS-4 as the standard character set */ +typedef uint32_t wchar_t; + +/* XXX: to be moveed elsewhere */ +typedef uint32_t mode_t; + +#endif /* !defined (__OHW_STDDEF_H__) */ diff --git a/qemu/roms/openhackware/src/libc/include/stdint.h b/qemu/roms/openhackware/src/libc/include/stdint.h new file mode 100644 index 000000000..1efd3b3fd --- /dev/null +++ b/qemu/roms/openhackware/src/libc/include/stdint.h @@ -0,0 +1,74 @@ +/* + * <stdint.h> + * + * Open Hack'Ware BIOS: arch dependent basic types + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined (__OHW_STDINT_H__) +#define __OHW_STDINT_H__ + +#if defined (__i386__) + +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned int uint32_t; +typedef signed int int32_t; +typedef unsigned long long uint64_t; +typedef signed long long int64_t; + +#elif defined (__x86_64__) + +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned int uint32_t; +typedef signed int int32_t; +typedef unsigned long uint64_t; +typedef signed long int64_t; + +#elif defined (__powerpc__) || defined (_ARCH_PPC) + +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned int uint32_t; +typedef signed int int32_t; +typedef unsigned long long uint64_t; +typedef signed long long int64_t; + +#elif defined (__powerpc64__) || defined (_ARCH_PPC64) + +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned int uint32_t; +typedef signed int int32_t; +typedef unsigned long uint64_t; +typedef signed long int64_t; +#else + +#error "unsupported CPU architecture" + +#endif + +#endif /* !defined (__OHW_STDINT_H__) */ diff --git a/qemu/roms/openhackware/src/libc/include/stdio.h b/qemu/roms/openhackware/src/libc/include/stdio.h new file mode 100644 index 000000000..f6bca8657 --- /dev/null +++ b/qemu/roms/openhackware/src/libc/include/stdio.h @@ -0,0 +1,43 @@ +/* + * <stdio.h> + * + * Open Hack'Ware BIOS: subset of POSIX stdio definitions + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined (__OHW_STDIO_H__) +#define __OHW_STDIO_H__ + +/* va_list is defined here */ +#include <stdarg.h> +/* size_t is defined here */ +#include <stddef.h> + +#define EOF ((int)-1) + +int printf (const char *format, ...); +int dprintf (const char *format, ...); +int sprintf (char *str, const char *format, ...); +int snprintf (char *str, size_t size, const char *format, ...); +int vprintf (const char *format, va_list ap); +int vdprintf (const char *format, va_list ap); +int vsprintf (char *str, const char *format, va_list ap); +int vsnprintf (char *str, size_t size, const char *format, va_list ap); + +int rename (const char *oldpath, const char *newpath); + +#endif /* !defined (__OHW_STDIO_H__) */ diff --git a/qemu/roms/openhackware/src/libc/include/stdlib.h b/qemu/roms/openhackware/src/libc/include/stdlib.h new file mode 100644 index 000000000..d0fab6cd0 --- /dev/null +++ b/qemu/roms/openhackware/src/libc/include/stdlib.h @@ -0,0 +1,50 @@ +/* + * <stdlib.h> + * + * Open Hack'Ware BIOS: subset of POSIX stdlib definitions + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined (__OHW_STDLIB_H__) +#define __OHW_STDLIB_H__ + +#define NULL ((void *)0) + +/* size_t is declared here */ +#include <stddef.h> + +void *malloc (size_t size); +void free (void *ptr); +void *realloc (void *ptr, size_t size); + +/* memset is declared here */ +#include <string.h> + +static inline void *calloc (size_t nmemb, size_t size) +{ + void *ret; + + ret = malloc(nmemb * size); + if (ret != NULL) + memset(ret, 0, nmemb * size); + + return ret; +} + +int mkstemp (char *template); + +#endif /* !defined (__OHW_STDLIB_H__) */ diff --git a/qemu/roms/openhackware/src/libc/include/string.h b/qemu/roms/openhackware/src/libc/include/string.h new file mode 100644 index 000000000..a2c4e0ea5 --- /dev/null +++ b/qemu/roms/openhackware/src/libc/include/string.h @@ -0,0 +1,90 @@ +/* + * <string.h> + * + * Open Hack'Ware BIOS: subset of POSIX string definitions + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined (__OHW_STRING_H__) +#define __OHW_STRING_H__ + +/* size_t is declared here */ +#include <stddef.h> + +void *memcpy (void *dest, const void *src, size_t n); +void *memccpy (void *dest, const void *src, int c, size_t n); +void *mempcpy (void *dest, const void *src, size_t n); +void *memmove (void *dest, const void *src, size_t n); +void *memcmove (void *dest, const void *src, int c, size_t n); +void *mempmove (void *dest, const void *src, size_t n); +void *memset (void *s, int c, size_t n); +int memcmp (const void *s1, const void *s2, size_t n); +void *memchr (const void *s, int c, size_t n); +void *rawmemchr (const void *s, int c); +void *memrchr (const void *s, int c, size_t n); +void *memmem (const void *haystack, size_t haystacklen, + const void *needle, size_t neddlelen); +void *strcpy (char *dest, const char *src); +void *strncpy (char *dest, const char *src, size_t n); +char *strdup (const char *s); +char *strndup (const char *s, size_t n); +void *stpcpy (char *dest, const char *src); +void *stpncpy (char *dest, const char *src, size_t n); +char *strcat (char *dest, const char *src); +char *strncat (char *dest, const char *src, size_t n); +int strcmp (const char *s1, const char *s2); +int strcasecmp (const char *s1, const char *s2); +int strncmp (const char *s1, const char *s2, size_t n); +int strncasecmp (const char *s1, const char *s2, size_t n); +char *strchr (const char *s, int c); +char *strchrnul (const char *s, int c); +char *strrchr (const char *s, int c); +char *strstr (const char *haystack, const char *needle); +char *strcasestr (const char *haystack, const char *needle); +#if 0 // TODO +size_t strspn (const char *s, const char *accept); +size_t strcspn (const char *s, const char *reject); +char *strpbrk (const char *s, const char *accept); +char *strtok (char *s, const char *delim); +char *strtok_r (char *s, const char *delim, char **ptrptr); +char *strsep (char **stringp, const char *delim); +#endif // TODO +char *basename (char *path); +char *dirname (char *path); +size_t strlen (const char *s); +size_t strnlen (const char *s, size_t maxlen); + +#if 0 +static inline int ffs (int value) +{ + int tmp; + + __asm__ __volatile__ ("cntlzw %0, %1" : "=r" (tmp) : "r" (value)); + + return 32 - tmp; +} +#endif + +static inline int ffs (int value) +{ + return __builtin_ffs(value); +} + +int ffsl (long i); +int ffsll (long long i); + +#endif /* !defined (__OHW_STRING_H__) */ diff --git a/qemu/roms/openhackware/src/libc/include/strings.h b/qemu/roms/openhackware/src/libc/include/strings.h new file mode 100644 index 000000000..64c2cfd75 --- /dev/null +++ b/qemu/roms/openhackware/src/libc/include/strings.h @@ -0,0 +1,27 @@ +/* + * <strings.h> + * + * Open Hack'Ware BIOS: Fake header for POSIX compatibility + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined (__OHW_STRINGS_H__) +#define __OHW_STRINGS_H__ + +#include <string.h> + +#endif /* !defined (__OHW_STRINGS_H__) */ diff --git a/qemu/roms/openhackware/src/libc/include/unistd.h b/qemu/roms/openhackware/src/libc/include/unistd.h new file mode 100644 index 000000000..4199a0323 --- /dev/null +++ b/qemu/roms/openhackware/src/libc/include/unistd.h @@ -0,0 +1,43 @@ +/* + * <unistd.h> + * + * Open Hack'Ware BIOS: subset of POSIX unistd definitions + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined (__OHW_UNISTD_H__) +#define __OHW_UNISTD_H__ + +/* size_t is defined here */ +/* mode_t is defined here (SHOULD NOT !) */ +/* off_t is defined here */ +#include <stddef.h> + +int open (const char *pathname, int flags, mode_t mode); +int close (int fd); +ssize_t read (int fd, void *buf, size_t count); +ssize_t write (int fd, const void *buf, size_t count); +enum { + SEEK_SET = 0x01, + SEEK_CUR = 0x02, + SEEK_END = 0x03, +}; +off_t lseek (int fd, off_t offset, int whence); +int truncate (const char *path, off_t length); +int ftruncate (int fd, off_t length); + +#endif /* !defined (__OHW_UNISTD_H__) */ diff --git a/qemu/roms/openhackware/src/libc/src/errno.c b/qemu/roms/openhackware/src/libc/src/errno.c new file mode 100644 index 000000000..3417998de --- /dev/null +++ b/qemu/roms/openhackware/src/libc/src/errno.c @@ -0,0 +1,25 @@ +/* + * <errno.c> + * + * Open Hack'Ware BIOS: errno management + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "errno.h" + +/* XXX: to fix */ +struct task cur_task; diff --git a/qemu/roms/openhackware/src/libc/src/format.c b/qemu/roms/openhackware/src/libc/src/format.c new file mode 100644 index 000000000..f62d5dc4e --- /dev/null +++ b/qemu/roms/openhackware/src/libc/src/format.c @@ -0,0 +1,467 @@ +/* + * <format.c> + * + * Open Hack'Ware BIOS: formated output functions + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* functions prototypes are here */ +#include <stdio.h> +/* va_list is defined here */ +#include <stdarg.h> +/* size_t is defined here */ +#include <stddef.h> +/* NULL is defined here */ +#include <stdlib.h> +/* write is defined here */ +#include <unistd.h> +/* memcpy is defined here */ +/* memset is defined here */ +/* strlen is defined here */ +#include <string.h> + +#define unused __attribute__ (( unused )) +int console_write (const void *buffer, int len); +/* XXX: this is a hack to be fixed */ +int serial_write (const void *buffer, int len); +#define debug_write serial_write + +/* Low level output fonctions */ +typedef size_t (*outf_t)(void *private, const unsigned char *buf, size_t len); + +/* output to fd */ +#if defined (__USE__vprintf__) +size_t outfd (void *private, const unsigned char *buf, size_t len) +{ + int *fd = private; + + if (*fd == 1 || *fd == 2) + return console_write(buf, len); + + return write(*fd, buf, len); +} + +size_t outf_dbg (void *private, const unsigned char *buf, size_t len) +{ + int *fd = private; + + if (*fd == 1 || *fd == 2) + return debug_write(buf, len); + + return write(*fd, buf, len); +} + +/* output to buffer */ +size_t outbuf (void *private, const unsigned char *buf, size_t len) +{ + unsigned char **dst = private; + + memcpy(*dst, buf, len); + (*dst) += len; + (*dst)[0] = '\0'; + + return len; +} + +/* misc formatted output functions */ +/* out one character */ +static size_t outc (outf_t outf, void *private, + unsigned int value, size_t maxlen) +{ + unsigned char buffer; + + if (maxlen < 1) + return 0; + buffer = value; + if ((*outf)(private, &buffer, 1) == (size_t)-1) + return -1; + + return 1; +} + +/* out one int in decimal */ +static size_t outdecs (outf_t outf, void *private, + int value, size_t fill, size_t maxlen) +{ + unsigned char buffer[12]; + size_t pos, len; + int sign; + + buffer[11] = '\0'; + pos = 10; + if (value == 0) { + sign = 0; + buffer[pos--] = '0'; + } else { + if (value < 0) { + sign = -1; + value = -value; + } else { + sign = 1; + } + for (; value != 0; pos--) { + buffer[pos] = (value % 10) + '0'; + value = value / 10; + } + } + if (fill != 0) + fill -= pos - 10; + for (; fill != 0 && pos != 0; fill--) { + buffer[pos--] = '0'; + } + if (sign == -1) + buffer[pos--] = '-'; + len = 10 - pos; + if (len > maxlen) + len = maxlen; + if ((*outf)(private, buffer + pos + 1, len) == (size_t)-1) + return -1; + + return len; +} + +/* out one unsigned int as decimal */ +static size_t outdecu (outf_t outf, void *private, + unsigned int value, size_t fill, size_t maxlen) +{ + unsigned char buffer[11]; + size_t pos, len; + + buffer[10] = '\0'; + pos = 9; + if (value == 0) { + buffer[pos--] = '0'; + } else { + for (; value != 0; pos--) { + buffer[pos] = (value % 10) + '0'; + value = value / 10; + } + } + if (fill != 0) + fill -= pos - 9; + for (; fill != 0 && pos != (size_t)-1; fill--) { + buffer[pos--] = '0'; + } + len = 9 - pos; + if (len > maxlen) + len = maxlen; + if ((*outf)(private, buffer + pos + 1, len) == (size_t)-1) + return -1; + + return len; +} + +/* out one unsigned int as hexadecimal */ +static size_t outhex (outf_t outf, void *private, + unsigned int value, size_t fill, size_t maxlen) +{ + unsigned char buffer[9]; + size_t pos, len; + int d; + + buffer[8] = '\0'; + pos = 7; + if (value == 0) { + buffer[pos--] = '0'; + } else { + for (; value != 0; pos--) { + d = value & 0xF; + if (d > 9) + d += 'a' - '0' - 10; + buffer[pos] = d + '0'; + value = value >> 4; + } + } + if (fill > 0) + fill -= pos - 7; + for (; fill != 0 && pos != (size_t)-1; fill--) { + buffer[pos--] = '0'; + } + len = 7 - pos; + if (len > maxlen) + len = maxlen; + if ((*outf)(private, buffer + pos + 1, len) == (size_t)-1) + return -1; + + return len; +} + +static size_t outstr (outf_t outf, void *private, + const unsigned char *str, unused size_t fill, + size_t maxlen) +{ +#define TMPBUF_LEN 256 +#if 0 + unsigned char tmpbuf[TMPBUF_LEN]; + size_t len, totlen, tmp; +#else + size_t len, totlen; +#endif + + if (str == NULL) { + /* Avoid crash if given a NULL string */ + str = "<null>"; + } + len = strlen(str); + totlen = 0; +#if 0 + if (len < fill) { + memset(tmpbuf, ' ', TMPBUF_LEN); + fill -= len; + for (; fill > 0; fill -= tmp) { + tmp = fill; + if (tmp > TMPBUF_LEN) + tmp = TMPBUF_LEN; + totlen += tmp; + if (totlen > maxlen) { + tmp = maxlen - totlen; + totlen = maxlen; + } + (*outf)(private, tmpbuf, tmp); + } + } +#endif + totlen += len; + if (totlen > maxlen) { + len = maxlen - totlen; + totlen = maxlen; + } + if ((*outf)(private, str, len) == (size_t)-1) + return -1; + + return totlen; +} + +int _vprintf(outf_t outf, void *private, size_t maxlen, + const unsigned char *format, va_list ap) +{ + const unsigned char *p, *str; + size_t maxfill, totlen, len, tmp; + int cur; + + cur = 0; + str = format; + for (totlen = 0; totlen != maxlen;) { + for (p = str; (*p != '%' || cur > 6) && *p != '\0'; p++) + continue; + len = p - str; + if (len + totlen > maxlen) + len = maxlen - totlen; + tmp = (*outf)(private, str, p - str); + if (tmp == (size_t)-1) + return -1; + totlen += tmp; + if (*p == '\0') + break; + maxfill = -2; + str = p; + next: + p++; + switch (*p) { + case '\0': + /* Invalid format */ + goto invalid; + case '0': + if (maxfill >= (size_t)-2) { + maxfill = -1; + goto next; + } + /* No break here */ + case '1' ... '9': + switch (maxfill) { + case -2: + /* Invalid format */ + goto invalid; + case -1: + maxfill = *p - '0'; + break; + default: + maxfill = (maxfill * 10) + *p - '0'; + break; + } + goto next; + case 'l': + /* Ignore it */ + goto next; + case 'h': + /* Ignore it */ + goto next; + case 'd': + if (maxfill == (size_t)-2 || maxfill == (size_t)(-1)) + maxfill = 0; + tmp = outdecs(outf, private, + va_arg(ap, int), maxfill, maxlen - totlen); + break; + case 'u': + if (maxfill == (size_t)-2 || maxfill == (size_t)(-1)) + maxfill = 0; + tmp = outdecu(outf, private, + va_arg(ap, unsigned int), maxfill, maxlen - totlen); + break; + case 'x': + if (maxfill == (size_t)-2 || maxfill == (size_t)(-1)) + maxfill = 0; + tmp = outhex(outf, private, + va_arg(ap, unsigned int), maxfill, maxlen - totlen); + break; + case 'p': + if (p != str + 1) { + /* Invalid format */ + goto invalid; + } else { + if (maxfill == (size_t)-2 || maxfill == (size_t)(-1)) + maxfill = 0; + tmp = outhex(outf, private, va_arg(ap, unsigned int), + maxfill, maxlen - totlen); + } + break; + case 'c': + if (p != str + 1) { + /* Invalid format */ + goto invalid; + } else { + tmp = outc(outf, private, + va_arg(ap, int), maxlen - totlen); + } + break; + case 's': + if (maxfill == (size_t)-2 || maxfill == (size_t)(-1)) + maxfill = 0; + str = va_arg(ap, const unsigned char *); + tmp = outstr(outf, private, str, maxfill, maxlen - totlen); + break; + case '%': + if (p != str + 1) { + /* Invalid format */ + goto invalid; + } else { + tmp = outc(outf, private, '%', maxlen - totlen); + } + default: + invalid: + /* Invalid format : display the raw string */ + len = p - str + 1; + if (len + totlen > maxlen) + len = maxlen - totlen; + tmp = (*outf)(private, str, len); + break; + } + if (tmp == (size_t)-1) + return -1; + totlen += tmp; + str = p + 1; + } + + return 0; +} +#else /* defined (__USE__vprintf__) */ +size_t outfd (void *private, const unsigned char *buf, size_t len); +size_t outf_dbg (void *private, const unsigned char *buf, size_t len); +size_t outbuf (void *private, const unsigned char *buf, size_t len); +int _vprintf(outf_t outf, void *private, size_t maxlen, + const unsigned char *format, va_list ap); +#endif /* defined (__USE__vprintf__) */ + +#if defined (__USE_printf__) +int printf (const char *format, ...) +{ + va_list ap; + int fd = 1; + int ret; + + va_start(ap, format); + ret = _vprintf(&outfd, &fd, -1, format, ap); + va_end(ap); + + return ret; +} +#endif /* defined (__USE_printf__) */ + +#if defined (__USE_dprintf__) +int dprintf (const char *format, ...) +{ + va_list ap; + int fd = 1; + int ret; + + va_start(ap, format); + ret = _vprintf(&outf_dbg, &fd, -1, format, ap); + va_end(ap); + + return ret; +} +#endif /* defined (__USE_dprintf__) */ + +#if defined (__USE_sprintf__) +int sprintf (char *str, const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = _vprintf(&outbuf, &str, -1, format, ap); + va_end(ap); + + return ret; +} +#endif /* defined (__USE_sprintf__) */ + +#if defined (__USE_snprintf__) +int snprintf (char *str, size_t size, const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = _vprintf(&outbuf, &str, size, format, ap); + va_end(ap); + + return ret; +} +#endif /* defined (__USE_snprintf__) */ + +#if defined (__USE_vprintf__) +int vprintf (const char *format, va_list ap) +{ + int fd = 1; + + return _vprintf(&outfd, &fd, -1, format, ap); +} +#endif /* defined (__USE_vprintf__) */ + +#if defined (__USE_vdprintf__) +int vdprintf (const char *format, va_list ap) +{ + int fd = 1; + + return _vprintf(&outf_dbg, &fd, -1, format, ap); +} +#endif /* defined (__USE_vdprintf__) */ + +#if defined (__USE_vsprintf__) +int vsprintf (char *str, const char *format, va_list ap) +{ + return _vprintf(&outbuf, &str, -1, format, ap); +} +#endif /* defined (__USE_vsprintf__) */ + +#if defined (__USE_vsnprintf__) +int vsnprintf (char *str, size_t size, const char *format, va_list ap) +{ + return _vprintf(&outbuf, &str, size, format, ap); +} +#endif /* defined (__USE_vsnprintf__) */ diff --git a/qemu/roms/openhackware/src/libc/src/malloc.c b/qemu/roms/openhackware/src/libc/src/malloc.c new file mode 100644 index 000000000..14bd8e557 --- /dev/null +++ b/qemu/roms/openhackware/src/libc/src/malloc.c @@ -0,0 +1,730 @@ +/* + * <malloc.c> + * + * Open Hack'Ware BIOS: memory management + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* functions prototypes are here */ +/* NULL is declared here */ +#include <stdlib.h> +/* memcpy is defined here */ +#include <string.h> +/* set_errno is defined here */ +#include <errno.h> + +//#define DEBUG_MEMOPS +#if defined (DEBUG_MEMOPS) +#define MEMOPS_PRINTF(fmt, args...) do { dprintf(fmt , ##args); } while (0) +#else +#define MEMOPS_PRINTF(fmt, args...) do { } while (0) +#endif + +#define unused __attribute__ (( unused )) + +/* XXX: TODO: put this elsewhere */ +void *page_get (int nb_pages); +void page_put (void *addr, int nb_pages); + +/* XXX: TOTO: put this elsewhere */ +#if defined (__i386__) +#define NATURAL_ALIGN_BITS 2 +#define PAGE_BITS 12 +#define __32_BITS 1 +#elif defined (__powerpc__) || defined (_ARCH_PPC) +#define NATURAL_ALIGN_BITS 2 +#define PAGE_BITS 12 +#define __32_BITS 1 +#elif defined (__x86_64__) +#define NATURAL_ALIGN_BITS 3 +#define PAGE_BITS 12 +#else +#error "Unsupported architecture" +#endif +#define PAGE_SIZE (1 << PAGE_BITS) +#define PAGE(addr) ((void *)((unsigned long)(addr) & ~(PAGE_SIZE - 1))) + + +#define MIN_ELEM_BITS (NATURAL_ALIGN_BITS + 1) +#define MIN_ELEM_SIZE (1 << (MIN_ELEM_BITS)) +#define MAX_ELEM_BITS (PAGE_BITS) +#define MAX_ELEM_SIZE (1 << (MAX_ELEM_BITS - 1)) +#define POOL_MAX ((MAX_ELEM_BITS) - (MIN_ELEM_BITS)) +#define CACHE_MAX 16 + +typedef struct free_slot_t free_slot_t; +struct free_slot_t { + struct free_slot_t *next; +}; + +typedef struct page_descr_t page_descr_t; +struct page_descr_t { + struct page_descr_t *next; + struct page_descr_t *prev; + void *addr; + unsigned long nb; +}; + +/* + * This points to the first descriptor page where stand: + * - 1 descriptor for this page. + * - 1 decriptor pages list head. + * - POOL_MAX pool descriptors list heads. + * - CACHE_MAX page cache entries list heads. + */ +static void *malloc_base; + +/* Shared functions */ +static inline page_descr_t *main_descr_get (void) +{ + return (page_descr_t *)malloc_base + 1; +} + +static inline page_descr_t *pool_head_get (int pool_idx) +{ + return main_descr_get() + 1 + pool_idx; +} + +static inline page_descr_t *cache_head_get (int cache_idx) +{ + return pool_head_get(POOL_MAX) + 1 + cache_idx; +} + +static void free_slots_init (void *page, int incr, int size) +{ + free_slot_t *slot, *next; + + for (slot = page; + slot < (free_slot_t *)((char *)page + size); slot = next) { + next = (void *)((char *)slot + incr); + slot->next = next; + } + slot = (void *)((char *)slot - incr); + slot->next = NULL; +} + +static page_descr_t *descr_find_free (page_descr_t *head_descr, + page_descr_t *skip_descr) +{ + page_descr_t *cur_descr, *best; + unsigned long max_used; + + /* Try to always return the page with the less free slots to reduce + * memory fragmentation. + */ + max_used = 0; + best = NULL; + for (cur_descr = head_descr->next; + cur_descr != head_descr; cur_descr = cur_descr->next) { + if (cur_descr != skip_descr && cur_descr->addr != NULL && + cur_descr->nb >= max_used) { + max_used = cur_descr->nb; + best = cur_descr; + } + } + + return best; +} + +/* Page descriptors management */ +static void page_descr_free (page_descr_t *head_descr) +{ + head_descr->next->prev = head_descr->prev; + head_descr->prev->next = head_descr->next; + page_put(head_descr, 1); +} + +static page_descr_t *page_descr_get (void) +{ + page_descr_t *main_descr, *head_descr, *page_descr; + free_slot_t *first_free; + + main_descr = main_descr_get(); + head_descr = main_descr->addr; + first_free = head_descr->addr; + if (first_free == NULL) { + /* Find a page with free descriptors */ + head_descr = descr_find_free(main_descr, NULL); + if (head_descr != NULL) { + /* Get the first free slot */ + first_free = head_descr->addr; + } else { + /* Allocate a new page */ + head_descr = page_get(1); + if (head_descr == NULL) { + MEMOPS_PRINTF("%s: cannot get new head descriptor\n", + __func__); + return NULL; + } + /* Initialise free slots */ + free_slots_init(head_descr, sizeof(page_descr_t), PAGE_SIZE); + /* Initialise page head descriptor */ + head_descr->addr = head_descr + 1; + head_descr->nb = 0; + head_descr->next = main_descr; + head_descr->prev = main_descr->prev; + /* Update main descriptor */ + main_descr->prev->next = head_descr; + main_descr->prev = head_descr; + main_descr->nb++; + first_free = head_descr->addr; + } + main_descr->addr = head_descr; + } + head_descr->addr = first_free->next; + if (head_descr->nb == 0) + main_descr->nb--; + head_descr->nb++; + page_descr = (page_descr_t *)first_free; + page_descr->prev = NULL; + page_descr->next = NULL; + page_descr->addr = NULL; + page_descr->nb = 0; + + return page_descr; +} + +static void page_descr_put (page_descr_t *page_descr) +{ + page_descr_t *main_descr, *head_descr, *next_descr, *free_descr; + free_slot_t *first_free, *next_free; + + head_descr = PAGE(page_descr); + /* Mark this descriptor as free */ + next_free = head_descr->addr; + first_free = (free_slot_t *)page_descr; + first_free->next = next_free; + /* Update page descriptor */ + head_descr->addr = first_free; + head_descr->nb--; + main_descr = main_descr_get(); + if (head_descr->nb == 0) { + /* Try to free this page */ + if (main_descr->addr == head_descr || + main_descr->addr == NULL || + main_descr->nb > 0) + free_descr = descr_find_free(main_descr, head_descr); + else + free_descr = main_descr->addr; + if (free_descr != NULL) { + /* Update main descriptor */ + page_descr_free(head_descr); + main_descr->addr = free_descr; + } else { + main_descr->addr = head_descr; + main_descr->nb++; + } + } else if (next_free == NULL) { + free_descr = head_descr; + for (head_descr = main_descr->next; + main_descr->nb > 0 && head_descr != main_descr; + head_descr = next_descr) { + next_descr = head_descr->next; + if (head_descr->nb == 0) { + if (main_descr->addr == head_descr) + main_descr->addr = NULL; + page_descr_free(head_descr); + main_descr->nb--; + } + } + if (main_descr->addr == NULL) + main_descr->addr = free_descr; + } +} + +/* Page cache management */ +static inline unsigned long cache_idx (void *addr) +{ + return ((unsigned long)addr >> PAGE_BITS) & (CACHE_MAX - 1); +} + +static inline unsigned long page_cache_pool_idx (page_descr_t *cache_descr) +{ + return (cache_descr->nb & 0xF); +} + +static inline page_descr_t *page_cache_page_descr (page_descr_t *cache_descr) +{ + return (page_descr_t *)(cache_descr->nb & ~0xF); +} + +static int page_cache_add_page (page_descr_t *page_descr, int pool_idx) +{ + page_descr_t *main_descr, *cache_head, *cache_descr; + + main_descr = main_descr_get(); + cache_head = cache_head_get(cache_idx(page_descr->addr)); + cache_descr = page_descr_get(); + if (cache_descr == NULL) { + MEMOPS_PRINTF("%s: cannot get cache page\n", __func__); + return -1; + } + cache_descr->nb = pool_idx | (unsigned long)page_descr; + cache_descr->prev = cache_head; + cache_descr->next = cache_head->next; + cache_descr->addr = page_descr->addr; + cache_head->next->prev = cache_descr; + cache_head->next = cache_descr; + + return 0; +} + +static page_descr_t *page_cache_get_descr (void *addr) +{ + page_descr_t *main_descr, *cache_head, *cache_descr; + + main_descr = main_descr_get(); + cache_head = cache_head_get(cache_idx(addr)); + for (cache_descr = cache_head->next; + cache_descr != cache_head; cache_descr = cache_descr->next) { + if (cache_descr->addr == addr) { + return cache_descr; + } + } + MEMOPS_PRINTF("%s: cannot get cache page descr\n", __func__); + + return NULL; +} + +static void page_cache_remove_descr (page_descr_t *cache_descr) +{ + cache_descr->next->prev = cache_descr->prev; + cache_descr->prev->next = cache_descr->next; + page_descr_put(cache_descr); +} + +/* Allocation by pool (size <= PAGE_SIZE / 2) */ +static void pool_descr_free (page_descr_t *cache_descr, + page_descr_t *pool_descr) +{ + page_put(PAGE(pool_descr->addr), 1); + page_cache_remove_descr(cache_descr); + pool_descr->next->prev = pool_descr->prev; + pool_descr->prev->next = pool_descr->next; + page_descr_put(pool_descr); +} + +static void *pool_malloc (int pool_idx) +{ + page_descr_t *main_descr, *pool_head, *pool_descr; + free_slot_t *first_free, *next_free; + + main_descr = main_descr_get(); + pool_head = pool_head_get(pool_idx); + pool_descr = pool_head->addr; + if (pool_descr == NULL || pool_descr->addr == NULL) { + pool_descr = descr_find_free(pool_head, NULL); + if (pool_descr == NULL) { + pool_descr = page_descr_get(); + if (pool_descr == NULL) { + MEMOPS_PRINTF("%s: cannot get pool descr\n", __func__); + return NULL; + } + pool_descr->addr = page_get(1); + if (pool_descr->addr == NULL) { + MEMOPS_PRINTF("%s: cannot allocate new page\n", __func__); + page_descr_put(pool_descr); + return NULL; + } + if (page_cache_add_page(pool_descr, pool_idx) < 0) { + MEMOPS_PRINTF("%s: cannot add new page to cache\n", __func__); + page_put(pool_descr->addr, 1); + page_descr_put(pool_descr); + return NULL; + } + free_slots_init(pool_descr->addr, + 1 << (MIN_ELEM_BITS + pool_idx), PAGE_SIZE); + pool_descr->nb = 0; + pool_descr->prev = pool_head->prev; + pool_descr->next = pool_head; + pool_head->prev->next = pool_descr; + pool_head->prev = pool_descr; + pool_head->nb++; + } + pool_head->addr = pool_descr; + } + first_free = pool_descr->addr; + next_free = first_free->next; + // memset(first_free, 0, 1 << (MIN_ELEM_BITS + pool_idx)); + pool_descr->addr = next_free; + if (pool_descr->nb == 0) + pool_head->nb--; + pool_descr->nb++; + + return first_free; +} + +unused static void pool_free (page_descr_t *cache_descr, void *area) +{ + page_descr_t *pool_head, *pool_descr, *pool_next, *free_pool; + free_slot_t *first_free, *next_free; + unsigned long size, pool_idx; + + pool_descr = page_cache_page_descr(cache_descr); + first_free = area; + next_free = pool_descr->addr; + pool_idx = page_cache_pool_idx(cache_descr); + size = 1 << (MIN_ELEM_BITS + pool_idx); + first_free->next = next_free; + pool_descr->addr = first_free; + pool_descr->nb--; + pool_head = pool_head_get(pool_idx); + if (pool_descr->nb == 0) { + if (pool_head->addr == pool_descr || + pool_head->addr == NULL || + pool_head->nb > 0) + free_pool = descr_find_free(pool_head, pool_descr); + else + free_pool = pool_head->addr; + if (free_pool != NULL) { + /* Free page & descriptor */ + pool_descr_free(cache_descr, pool_descr); + pool_head->addr = free_pool; + } else { + pool_head->addr = pool_descr; + pool_head->nb++; + } + } else if (next_free == NULL) { + free_pool = pool_descr; + for (pool_descr = pool_head->next; + pool_head->nb > 0 && pool_descr != pool_head; + pool_descr = pool_next) { + pool_next = pool_descr->next; + if (pool_descr->nb == 0) { + if (pool_head->addr == pool_descr) + pool_head->addr = NULL; + cache_descr = page_cache_get_descr(PAGE(pool_descr->addr)); + if (cache_descr != NULL) { + pool_descr_free(cache_descr, pool_descr); + pool_head->nb--; + } else { + /* Incoherency: what to do ? */ + } + } + } + if (pool_head->addr == NULL) + pool_head->addr = free_pool; + } +} + +/* Big area management (size > PAGE_SIZE / 2) */ +static void *big_malloc (int nb_pages) +{ + page_descr_t *main_descr, *pool_head, *pool_descr; + + main_descr = main_descr_get(); + pool_head = pool_head_get(POOL_MAX); + pool_descr = page_descr_get(); + if (pool_descr == NULL) { + MEMOPS_PRINTF("%s: cannot get pool descr\n", __func__); + return NULL; + } + pool_descr->addr = page_get(nb_pages); + if (pool_descr->addr == NULL) { + page_descr_put(pool_descr); + MEMOPS_PRINTF("%s: cannot get page\n", __func__); + return NULL; + } + if (page_cache_add_page(pool_descr, POOL_MAX) < 0) { + page_put(pool_descr->addr, nb_pages); + page_descr_put(pool_descr); + MEMOPS_PRINTF("%s: cannot get add page to cache\n", __func__); + return NULL; + } + pool_descr->prev = pool_head->prev; + pool_descr->next = pool_head; + pool_descr->nb = nb_pages; + pool_head->prev->next = pool_descr; + pool_head->prev = pool_descr; + + return pool_descr->addr; +} + +static void big_free (page_descr_t *cache_descr) +{ + page_descr_t *pool_descr; + + pool_descr = page_cache_page_descr(cache_descr); + if (pool_descr->addr != NULL && pool_descr->nb != 0) { + page_put(pool_descr->addr, pool_descr->nb); + pool_descr->next->prev = pool_descr->prev; + pool_descr->prev->next = pool_descr->next; + page_descr_put(pool_descr); + page_cache_remove_descr(cache_descr); + } else { + MEMOPS_PRINTF("%s: ERROR %p %d\n", + __func__, pool_descr->addr, (int)pool_descr->nb); + } +} + +unused static void *big_realloc (page_descr_t *cache_descr, int new_size) +{ + void *new_area; + page_descr_t *pool_descr; + unsigned long new_nb; + + pool_descr = page_cache_page_descr(cache_descr); + new_nb = (new_size + PAGE_SIZE - 1) / PAGE_SIZE; + if (new_nb == pool_descr->nb) { + new_area = cache_descr->addr; + } else { + new_area = big_malloc(new_size); + memcpy(new_area, cache_descr->addr, pool_descr->nb * PAGE_SIZE); + big_free(cache_descr); + } + + return new_area; +} + +/* Global entry points */ +int page_descrs_init (void) +{ + page_descr_t *main_descr, *page_descr, *pool_head, *cache_head; + int i; + + /* Allocate first descriptor page */ + malloc_base = page_get(1); + if (malloc_base == NULL) { + set_errno(ENOMEM); + MEMOPS_PRINTF("%s: cannot get main descriptor\n", __func__); + return -1; + } + /* Init free slots in this page */ + free_slots_init(malloc_base, sizeof(page_descr_t), PAGE_SIZE); + /* Init main descriptor */ + page_descr = malloc_base; + main_descr = main_descr_get(); + main_descr->addr = page_descr; + main_descr->nb = 0; + main_descr->next = page_descr; + main_descr->prev = page_descr; + page_descr->nb = 1; + page_descr->addr = page_descr + 2; + page_descr->next = main_descr; + page_descr->prev = main_descr; + /* Init pool lists heads */ + for (i = 0; i <= POOL_MAX; i++) { + pool_head = page_descr_get(); + if (pool_head == NULL) { + page_put(malloc_base, 1); + malloc_base = NULL; + MEMOPS_PRINTF("%s: cannot get pool descriptor %d\n", __func__, i); + return -1; + } + pool_head->prev = pool_head; + pool_head->next = pool_head; + pool_head->addr = NULL; + } + /* Init page caches lists heads */ + for (i = 0; i < CACHE_MAX; i++) { + cache_head = page_descr_get(); + if (cache_head == NULL) { + page_put(malloc_base, 1); + malloc_base = NULL; + MEMOPS_PRINTF("%s: cannot get page cache descriptor %d\n", + __func__, i); + return -1; + } + cache_head->prev = cache_head; + cache_head->next = cache_head; + } + + return 0; +} + +static inline int get_pool_idx (size_t size) +{ + int pool_idx; + + pool_idx = 0; + for (size /= MIN_ELEM_SIZE; size != 0; size = size / 2) + pool_idx++; + + return pool_idx; +} + +#if 1 +void *malloc (size_t size) +{ + void *ret; + int pool_idx; + + if (malloc_base == NULL || size == 0) { + ret = NULL; + } else if (size >= MAX_ELEM_SIZE) { + ret = big_malloc((size + PAGE_SIZE - 1) / PAGE_SIZE); + } else { + if (size <= MIN_ELEM_SIZE) + pool_idx = 0; + else { + pool_idx = get_pool_idx(size); + } + ret = pool_malloc(pool_idx); + } + if (ret != NULL) + memset(ret, 0, size); +#if 0 + memory_dump(); + printf("%s(%d) => %p\n", __func__, size, ret); +#endif + + return ret; +} +#endif + +#if 0 +void free (void *area) +{ + page_descr_t *cache_descr; + int pool_idx; + + if (malloc_base == NULL || area == NULL) + return; + cache_descr = page_cache_get_descr(PAGE(area)); + if (cache_descr != NULL) { + pool_idx = page_cache_pool_idx(cache_descr); + if (pool_idx == POOL_MAX) { + big_free(cache_descr); + } else { + pool_free(cache_descr, area); + } + } else { + /* Given area is not valid */ + MEMOPS_PRINTF("ERROR: area to free not found: %p\n", area); + } +} +#endif + +#if 0 +void *realloc (void *area, size_t new_size) +{ + void *new_area; + page_descr_t *pool_descr, *cache_descr; + size_t size; + int pool_idx, new_pool_idx; + + if (malloc_base == NULL || new_size == 0) { + free(area); + return NULL; + } + if (area == NULL) + return malloc(new_size); + cache_descr = page_cache_get_descr(PAGE(area)); + if (cache_descr == NULL) { + /* Given area is not valid */ + return NULL; + } + pool_idx = page_cache_pool_idx(cache_descr); + if (new_size >= MAX_ELEM_SIZE) { + new_pool_idx = POOL_MAX; + if (pool_idx == POOL_MAX) + return big_realloc(cache_descr, new_size); + } else { + if (new_size <= MIN_ELEM_SIZE) + new_pool_idx = 0; + else + new_pool_idx = get_pool_idx(size); + if (pool_idx == new_pool_idx) + return area; + } + /* Common case: alloc, copy & free */ + if (new_pool_idx == POOL_MAX) + new_area = big_malloc((new_size + PAGE_SIZE - 1) / PAGE_SIZE); + else + new_area = pool_malloc(new_pool_idx); + if (new_area == NULL) + return NULL; + if (pool_idx == POOL_MAX) { + pool_descr = page_cache_page_descr(cache_descr); + size = pool_descr->nb * PAGE_SIZE; + } else { + size = MIN_ELEM_SIZE << pool_idx; + } + memcpy(new_area, area, size); + if (pool_idx == POOL_MAX) + big_free(cache_descr); + else + pool_free(cache_descr, area); + + return new_area; +} +#endif + +void memory_dump (void) +{ +#if defined (DEBUG_MEMOPS) + page_descr_t *main_descr, *page_descr; + page_descr_t *pool_head, *pool_descr, *cache_head, *cache_descr; + int i, n; + + main_descr = main_descr_get(); + /* Dump descriptor pages */ + printf("Descriptor pages dump: %p max=%d %d pages with no alloc descrs\n", + main_descr, (int)(PAGE_SIZE / sizeof(page_descr_t)), (int)main_descr->nb); + n = 0; + for (page_descr = main_descr->next; + page_descr != main_descr; page_descr = page_descr->next) { + printf("Descr %d : %p %p used: %d\n", + n, page_descr, page_descr->addr, (int)page_descr->nb); + n++; + } + /* Dump pool areas pages */ + for (i = 0; i < POOL_MAX; i++) { + n = 0; + pool_head = pool_head_get(i); + printf("Pool %d %p\n", i, pool_head); + for (pool_descr = pool_head->next; + pool_descr != pool_head; pool_descr = pool_descr->next) { + printf("Pool %d descr %d : %p %p used: %d size %d free: %p %p\n", + i, n, pool_descr, PAGE(pool_descr->addr), (int)pool_descr->nb, + 1 << (MIN_ELEM_BITS + i), pool_descr->addr, + ((free_slot_t *)pool_descr->addr)->next); + n++; + } + printf(" => %d pages allocated\n", n); + } +#if 0 + /* Dump big area pages */ + printf("Pool %d\n", POOL_MAX); + n = 0; + pool_head = pool_head_get(POOL_MAX); + for (pool_descr = pool_head->next; + pool_descr != pool_head; pool_descr = pool_descr->next) { + printf("Pool %d descr %d : %p nb pages: %d\n", + POOL_MAX, n, pool_descr->addr, (int)pool_descr->nb); + n++; + } + printf(" => %d pages allocated\n", n); + /* Dump page cache */ + for (i = 0; i < CACHE_MAX; i++) { + printf("Page cache 0x____%x___\n", i); + n = 0; + cache_head = cache_head_get(i); + for (cache_descr = cache_head->next; + cache_descr != cache_head; cache_descr = cache_descr->next) { + pool_descr = page_cache_page_descr(cache_descr); + printf("Cache %d descr %d : %p pool: %d descr: %p %p %d\n", + i, n, cache_descr->addr, + (int)page_cache_pool_idx(cache_descr), + pool_descr, pool_descr->addr, (int)pool_descr->nb); + n++; + } + printf(" => %d pages allocated\n", n); + } +#endif +#endif +} diff --git a/qemu/roms/openhackware/src/libc/src/mem.c b/qemu/roms/openhackware/src/libc/src/mem.c new file mode 100644 index 000000000..a75ff851c --- /dev/null +++ b/qemu/roms/openhackware/src/libc/src/mem.c @@ -0,0 +1,251 @@ +/* + * <mem.c> + * + * Open Hack'Ware BIOS: mem<xxx> functions + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* functions prototypes are here */ +#include <string.h> +/* NULL is declared here */ +#include <stdlib.h> + +/* mem___ functions */ +#if defined (__USE_memcpy__) +void *memcpy (void *dest, const void *src, size_t n) +{ + const char *p; + char *q; + + p = src; + q = dest; + for (; n != 0; n--) + *q++ = *p++; + + return dest; +} +#endif + +#if defined (__USE_memccpy__) +void *memccpy (void *dest, const void *src, int c, size_t n) +{ + const char *p; + char *q, *r; + + p = src; + q = dest; + r = NULL; + for (; n != 0; n--, q++) { + *q = *p++; + if (*q == c) { + r = q; + break; + } + } + + return r; +} +#endif + +#if defined (__USE_mempcpy__) +/* GNU extension */ +void *mempcpy (void *dest, const void *src, size_t n) +{ + const char *p; + char *q; + + p = src; + q = dest; + for (; n != 0; n--) + *q++ = *p++; + + return q; +} +#endif + +#if defined (__USE_memmove__) +void *memmove (void *dest, const void *src, size_t n) +{ + const char *p; + char *q; + + p = src; + q = dest; + if (dest <= src) { + for (; n != 0; n--) + *q++ = *p++; + } else { + p += n; + q += n; + for (; n != 0; n--) + *--q = *--p; + } + + return dest; +} +#endif + +#if defined (__USE_memcmove__) +/* OHW extension */ +void *memcmove (void *dest, const void *src, int c, size_t n) +{ + const char *p; + char *q, *r; + + p = src; + q = dest; + r = NULL; + if (dest <= src) { + for (; n != 0; n--, q++) { + *q++ = *p++; + if (*q == c) { + r = q; + break; + } + } + } else { + p += n; + q += n; + for (; n != 0; n--, q--) { + *--q = *--p; + if (*q == c) { + r = q; + break; + } + } + } + + return dest; +} +#endif + +#if defined (__USE_mempmove__) +/* OHW extension */ +void *mempmove (void *dest, const void *src, size_t n) +{ + const char *p; + char *q, *r; + + p = src; + q = dest; + r = q + n; + if (dest <= src) { + for (; n != 0; n--) + *q++ = *p++; + } else { + p += n; + q = r; + for (; n != 0; n--) + *--q = *--p; + } + + return r; +} +#endif + +#if defined (__USE_memset__) +void *memset (void *s, int c, size_t n) +{ + char *p; + + for (p = s; n != 0; n--) + *p++ = c; + + return s; +} +#endif + +#if defined (__USE_memcmp__) +int memcmp (const void *s1, const void *s2, size_t n) +{ + const char *p, *q; + int ret; + + p = s1; + q = s2; + for (ret = 0; n != 0 && ret == 0; n--) + ret = *p++ - *q++; + + return ret; +} +#endif + +#if defined (__USE_memchr__) +void *memchr (const void *s, int c, size_t n) +{ + const char *p, *r; + + r = NULL; + for (p = s; n != 0; n--, p++) { + if (*p == c) { + r = p; + break; + } + } + + return (void *)r; +} +#endif + +#if defined (__USE_rawmemchr__) +/* GNU extension */ +void *rawmemchr (const void *s, int c) +{ + const char *p; + + for (p = s; *p != c; p++) + continue; + + return (void *)p; +} +#endif + +#if defined (__USE_memrchr__) +void *memrchr (const void *s, int c, size_t n) +{ + const char *p, *r; + + r = NULL; + for (p = s + n; n != 0; n--, p--) { + if (*p == c) { + r = p; + break; + } + } + + return (void *)r; +} +#endif + +#if defined (__USE_memmem__) +/* GNU extension */ +void *memmem (const void *haystack, size_t haystacklen, + const void *needle, size_t neddlelen) +{ + const char *p, *r; + + r = NULL; + for (p = haystack; haystacklen > neddlelen; haystacklen--, p++) { + if (memcmp(p, needle, neddlelen) == 0) { + r = p; + break; + } + } + + return (void *)r; +} +#endif diff --git a/qemu/roms/openhackware/src/libc/src/str.c b/qemu/roms/openhackware/src/libc/src/str.c new file mode 100644 index 000000000..24548fa00 --- /dev/null +++ b/qemu/roms/openhackware/src/libc/src/str.c @@ -0,0 +1,430 @@ +/* + * <str.c> + * + * Open Hack'Ware BIOS: str<xxx> functions + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* functions prototypes are here */ +#include <string.h> +/* NULL is defined here */ +/* malloc is defined here */ +#include <stdlib.h> +/* toupper is defined here */ +#include <ctype.h> + +/* str___ functions */ +#if defined (__USE_strcpy__) +void *strcpy (char *dest, const char *src) +{ + char *q; + + q = dest; + for (; ; q++) { + *q = *src++; + if (*q == '\0') + break; + } + + return dest; +} +#endif + +#if defined (__USE_strncpy__) +void *strncpy (char *dest, const char *src, size_t n) +{ + char *q; + + q = dest; + for (; n != 0; n--, q++) { + *q = *src++; + if (*q == '\0') + break; + } + + return dest; +} +#endif + +#if defined (__USE_strdup__) +char *strdup (const char *s) +{ + char *dest; + size_t len; + + len = strlen(s) + 1; + dest = malloc(len); + if (dest != NULL) + memcpy(dest, s, len); + + return dest; +} +#endif + +#if defined (__USE_strndup__) +/* GNU extension */ +char *strndup (const char *s, size_t n) +{ + char *dest; + size_t len; + + len = strlen(s) + 1; + if (len > n) + len = n; + dest = malloc(len); + if (dest != NULL) { + memcpy(dest, s, len - 1); + dest[len - 1] = '\0'; + } + + return dest; +} +#endif + +#if defined (__USE_stpcpy__) +void *stpcpy (char *dest, const char *src) +{ + char *q; + + q = dest; + for (; ; q++) { + *q = *src++; + if (*q == '\0') + break; + } + + return q; +} +#endif + +#if defined (__USE_stpncpy__) +void *stpncpy (char *dest, const char *src, size_t n) +{ + char *q; + + q = dest; + for (; n != 0; n--, q++) { + *q = *src++; + if (*q == '\0') + break; + } + + return q; +} +#endif + +#if defined (__USE_strcat__) +char *strcat (char *dest, const char *src) +{ + char *q; + + for (q = dest + strlen(dest); ; q++) { + *q = *src++; + if (*q == '\0') + break; + } + + return dest; +} +#endif + +#if defined (__USE_strncat__) +char *strncat (char *dest, const char *src, size_t n) +{ + char *q; + + for (q = dest + strlen(dest); n != 0; n--, q++) { + *q = *src++; + if (*q == '\0') + break; + } + + return dest; +} +#endif + +#if defined (__USE_strcmp__) +int strcmp (const char *s1, const char *s2) +{ + int ret; + + for (ret = 0; ret == 0; s1++) { + ret = *s1 - *s2++; + if (*s1 == '\0') + break; + } + + return ret; +} +#endif + +#if defined (__USE_strcasecmp__) +int strcasecmp (const char *s1, const char *s2) +{ + int ret; + + for (ret = 0; ret == 0; s1++) { + ret = toupper(*s1) - toupper(*s2++); + if (*s1 == '\0') + break; + } + + return ret; +} +#endif + +#if defined (__USE_strncmp__) +int strncmp (const char *s1, const char *s2, size_t n) +{ + int ret; + + for (ret = 0; ret == 0 && n != 0; n--, s1++) { + ret = *s1 - *s2++; + if (*s1 == '\0') + break; + } + + return ret; +} +#endif + +#if defined (__USE_strncasecmp__) +int strncasecmp (const char *s1, const char *s2, size_t n) +{ + int ret; + + for (ret = 0; ret == 0 && n != 0; n--, s1++) { + ret = toupper(*s1) - toupper(*s2++); + if (*s1 == '\0') + break; + } + + return ret; +} +#endif + +#if defined (__USE_strchr__) +char *strchr (const char *s, int c) +{ + const char *r; + + for (r = NULL; *s != '\0'; s++) { + if (*s == c) { + r = s; + break; + } + } + + return (char *)r; +} +#endif + +#if defined (__USE_strchrnul__) +/* GNU extension */ +char *strchrnul (const char *s, int c) +{ + for (; *s != '\0' && *s != c; s++) + continue; + + return (char *)s; +} +#endif + +#if defined (__USE_strrchr__) +char *strrchr (const char *s, int c) +{ + const char *p, *r; + + r = NULL; + for (p = s + strlen(s); p != s; p--) { + if (*p == c) { + r = p; + break; + } + } + + return (char *)r; +} +#endif + +#if defined (__USE_strstr__) +char *strstr (const char *haystack, const char *needle) +{ + const char *r; + size_t hlen, nlen; + + if (*needle == '\0') + return (char *)haystack; + r = NULL; + hlen = strlen(haystack); + nlen = strlen(needle); + for (; hlen > nlen; hlen--, haystack++) { + if (memcmp(haystack, needle, nlen) == 0) { + r = haystack; + break; + } + } + + return (char *)r; +} +#endif + +#if defined (__USE_strcasestr__) +char *strcasestr (const char *haystack, const char *needle) +{ + const char *p, *q, *r; + size_t hlen, nlen, n; + + if (*needle == '\0') + return (char *)haystack; + r = NULL; + hlen = strlen(haystack); + nlen = strlen(needle); + for (; hlen > nlen; hlen--, haystack++) { + p = haystack; + q = needle; + for (n = nlen; n != 0; n--) { + if (toupper(*p++) != toupper(*q++)) + break; + } + if (n == 0) { + r = haystack; + break; + } + } + + return (char *)r; +} +#endif + +#if defined (__USE_strspn__) +#error "TODO" +size_t strspn (const char *s, const char *accept) +{ +} +#endif + +#if defined (__USE_strcspn__) +#error "TODO" +size_t strcspn (const char *s, const char *reject) +{ +} +#endif + +#if defined (__USE_strpbrk__) +#error "TODO" +char *strpbrk (const char *s, const char *accept) +{ +} +#endif + +#if defined (__USE_strtok__) +#error "TODO" +char *strtok (char *s, const char *delim) +{ +} +#endif + +#if defined (__USE_strtok_r__) +#error "TODO" +char *strtok_r (char *s, const char *delim, char **ptrptr) +{ +} +#endif + +#if defined (__USE_strsep__) +#error "TODO" +char *strsep (char **stringp, const char *delim) +{ +} +#endif + +#if defined (__USE_basename__) +char *basename (char *path) +{ + char *sl; + size_t len; + + if (path == NULL || (len = strlen(path)) == 0) + return strdup("."); + sl = path + len - 1; + if (*sl == '/') + sl--; + for (; sl != path; sl--) { + if (*sl == '/') + break; + } + + return strdup(sl + 1); +} +#endif + +#if defined (__USE_dirname__) +char *dirname (char *path) +{ + char *sl, *ret; + size_t len; + + if (path == NULL || (len = strlen(path)) == 0) { + ret = strdup("."); + } else { + sl = path + len - 1; + if (*sl == '/') + sl--; + for (; sl != path; sl--) { + if (*sl == '/') + break; + } + len = sl - path; + if (len == 0) { + ret = strdup("."); + } else { + ret = malloc(len + 1); + if (ret != NULL) { + memcpy(path, ret, len); + path[len] = '\0'; + } + } + } + + return ret; +} +#endif + +#if defined (__USE_strlen__) +size_t strlen (const char *s) +{ + size_t len; + + for (len = 0; *s != '\0'; len++) + s++; + + return len; +} +#endif + +#if defined (__USE_strnlen__) +size_t strnlen (const char *s, size_t maxlen) +{ + size_t len; + + for (len = 0; maxlen != 0 && *s != '\0'; maxlen--, len++) + s++; + + return len; +} +#endif |