From 61ba39a23786a7ae9694705af1d146c00a319144 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Sat, 5 Feb 2011 04:35:27 +0100 Subject: Getting rid of newlib, starting to implement a libc. Highly experimental, highly untested. --- libc/include/ctype.h | 20 +++++++ libc/include/errno.h | 140 +++++++++++++++++++++++++++++++++++++++++++++ libc/include/malloc.h | 18 ++++++ libc/include/math.h | 4 ++ libc/include/reent.h | 16 ++++++ libc/include/setjmp.h | 13 +++++ libc/include/stdio.h | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++ libc/include/stdlib.h | 12 ++++ libc/include/string.h | 97 ++++++++++++++++++++++++++++++++ libc/include/unistd.h | 31 ++++++++++ 10 files changed, 504 insertions(+) create mode 100644 libc/include/ctype.h create mode 100644 libc/include/errno.h create mode 100644 libc/include/malloc.h create mode 100644 libc/include/math.h create mode 100644 libc/include/reent.h create mode 100644 libc/include/setjmp.h create mode 100644 libc/include/stdio.h create mode 100644 libc/include/stdlib.h create mode 100644 libc/include/string.h create mode 100644 libc/include/unistd.h (limited to 'libc/include') diff --git a/libc/include/ctype.h b/libc/include/ctype.h new file mode 100644 index 0000000..22e3e81 --- /dev/null +++ b/libc/include/ctype.h @@ -0,0 +1,20 @@ +#ifndef __CTYPE_H__ +#define __CTYPE_H__ + +static inline int isascii(int c) { return (c & 0x80) == 0; } +static inline int isblank(int c) { return c == ' ' || c == '\t'; } +static inline int isdigit(int c) { return c >= '0' && c <= '9'; } +static inline int iscntrl(int c) { return c < 32; } +static inline int islower(int c) { return c >= 'a' && c <= 'z'; } +static inline int isspace(int c) { return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v'; } +static inline int isupper(int c) { return c >= 'A' && c <= 'Z'; } +static inline int isxdigit(int c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } + +static inline int isalpha(int c) { return isupper(c) || islower(c); } +static inline int isalnum(int c) { return isalpha(c) || isdigit(c); } +static inline int isgraph(int c) { return !iscntrl(c) && !isspace(c); } +static inline int isprint(int c) { return !iscntrl(c); } +static inline int ispunct(int c) { return !iscntrl(c) && !isspace(c) && !isalnum(c); } + + +#endif diff --git a/libc/include/errno.h b/libc/include/errno.h new file mode 100644 index 0000000..c88ea64 --- /dev/null +++ b/libc/include/errno.h @@ -0,0 +1,140 @@ +#ifndef __ERRNO_H__ +#define __ERRNO_H__ + +enum errno_t { + ENOERROR = 0, + EPERM = 1, + ENOENT = 2, + ESRCH = 3, + EINTR = 4, + EIO = 5, + ENXIO = 6, + E2BIG = 7, + ENOEXEC = 8, + EBADF = 9, + ECHILD = 10, + EAGAIN = 11, + ENOMEM = 12, + EACCES = 13, + EFAULT = 14, + ENOTBLK = 15, + EBUSY = 16, + EEXIST = 17, + EXDEV = 18, + ENODEV = 19, + ENOTDIR = 20, + EISDIR = 21, + EINVAL = 22, + ENFILE = 23, + EMFILE = 24, + ENOTTY = 25, + ETXTBSY = 26, + EFBIG = 27, + ENOSPC = 28, + ESPIPE = 29, + EROFS = 30, + EMLINK = 31, + EPIPE = 32, + EDOM = 33, + ERANGE = 34, + EDEADLK = 35, + ENAMETOOLONG = 36, + ENOLCK = 37, + ENOSYS = 38, + ENOTEMPTY = 39, + ELOOP = 40, + EWOULDBLOCK = EAGAIN, + ENOMSG = 42, + EIDRM = 43, + ECHRNG = 44, + EL2NSYNC = 45, + EL3HLT = 46, + EL3RST = 47, + ELNRNG = 48, + EUNATCH = 49, + ENOCSI = 50, + EL2HLT = 51, + EBADE = 52, + EBADR = 53, + EXFULL = 54, + ENOANO = 55, + EBADRQC = 56, + EBADSLT = 57, + EDEADLOCK = EDEADLK, + EBFONT = 59, + ENOSTR = 60, + ENODATA = 61, + ETIME = 62, + ENOSR = 63, + ENONET = 64, + ENOPKG = 65, + EREMOTE = 66, + ENOLINK = 67, + EADV = 68, + ESRMNT = 69, + ECOMM = 70, + EPROTO = 71, + EMULTIHOP = 72, + EDOTDOT = 73, + EBADMSG = 74, + EOVERFLOW = 75, + ENOTUNIQ = 76, + EBADFD = 77, + EREMCHG = 78, + ELIBACC = 79, + ELIBBAD = 80, + ELIBSCN = 81, + ELIBMAX = 82, + ELIBEXEC = 83, + EILSEQ = 84, + ERESTART = 85, + ESTRPIPE = 86, + EUSERS = 87, + ENOTSOCK = 88, + EDESTADDRREQ = 89, + EMSGSIZE = 90, + EPROTOTYPE = 91, + ENOPROTOOPT = 92, + EPROTONOSUPPORT = 93, + ESOCKTNOSUPPORT = 94, + EOPNOTSUPP = 95, + EPFNOSUPPORT = 96, + EAFNOSUPPORT = 97, + EADDRINUSE = 98, + EADDRNOTAVAIL = 99, + ENETDOWN = 100, + ENETUNREACH = 101, + ENETRESET = 102, + ECONNABORTED = 103, + ECONNRESET = 104, + ENOBUFS = 105, + EISCONN = 106, + ENOTCONN = 107, + ESHUTDOWN = 108, + ETOOMANYREFS = 109, + ETIMEDOUT = 110, + ECONNREFUSED = 111, + EHOSTDOWN = 112, + EHOSTUNREACH = 113, + EALREADY = 114, + EINPROGRESS = 115, + ESTALE = 116, + EUCLEAN = 117, + ENOTNAM = 118, + ENAVAIL = 119, + EISNAM = 120, + EREMOTEIO = 121, + EDQUOT = 122, + ENOMEDIUM = 123, + EMEDIUMTYPE = 124, + ECANCELED = 125, + ENOKEY = 126, + EKEYEXPIRED = 127, + EKEYREVOKED = 128, + EKEYREJECTED = 129, + EOWNERDEAD = 130, + ENOTRECOVERABLE = 131, + ERFKILL = 132, +}; + +#endif diff --git a/libc/include/malloc.h b/libc/include/malloc.h new file mode 100644 index 0000000..8dbfc05 --- /dev/null +++ b/libc/include/malloc.h @@ -0,0 +1,18 @@ +#ifndef __MALLOC_H__ +#define __MALLOC_H__ + +#include +#include +#include + +void * malloc(size_t size); +void free(void *ptr); +void * realloc(void *ptr, size_t size); + +static inline void * calloc(size_t nmemb, size_t size) { + void * r = malloc(nmemb * size); + memset(r, 0, nmemb * size); + return r; +} + +#endif diff --git a/libc/include/math.h b/libc/include/math.h new file mode 100644 index 0000000..b41fee0 --- /dev/null +++ b/libc/include/math.h @@ -0,0 +1,4 @@ +#ifndef __MATH_H__ +#define __MATH_H__ + +#endif diff --git a/libc/include/reent.h b/libc/include/reent.h new file mode 100644 index 0000000..c3633ee --- /dev/null +++ b/libc/include/reent.h @@ -0,0 +1,16 @@ +#ifndef __RENT_H__ +#define __RENT_H__ + +#include + +struct _reent { + enum errno_t _errno; +}; + +static inline void _REENT_INIT_PTR(struct _reent * reent) { + reent->_errno = ENOERROR; +} + +extern struct _reent * _impure_ptr; + +#endif diff --git a/libc/include/setjmp.h b/libc/include/setjmp.h new file mode 100644 index 0000000..8fc8a12 --- /dev/null +++ b/libc/include/setjmp.h @@ -0,0 +1,13 @@ +#ifndef __SETJMP_H__ +#define __SETJMP_H__ + +#include + +typedef struct { + uint32_t buf[32]; +} jmp_buf; + +int setjmp(jmp_buf env); +void longjmp(jmp_buf env, int val); + +#endif diff --git a/libc/include/stdio.h b/libc/include/stdio.h new file mode 100644 index 0000000..1be0c6e --- /dev/null +++ b/libc/include/stdio.h @@ -0,0 +1,153 @@ +#ifndef __STDIO_H__ +#define __STDIO_H__ + +#include +#include +#include +#include +#include + +struct _FILE { + int fd; +}; + +typedef struct _FILE FILE; + +int printf(const char * format, ...); +int fprintf(FILE *stream, const char * format, ...); +int sprintf(char * str, const char * format, ...); +int snprintf(char * str, size_t size, const char * format, ...); +int asprintf(char ** strp, const char * format, ...); + +int vprintf(const char * format, va_list ap); +int vfprintf(FILE *stream, 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 vasprintf(char ** strp, const char * format, va_list ap); + +void __sinit(struct _reent *); + +// We don't even buffer, so... +static inline int fflush(FILE *stream) { return 0; } + +// hopefully, since all of the mode crap is static, gcc will optimize most of it away. +static inline FILE * fopen(const char * fname, const char * mode) { + FILE * r = NULL; + int flags = 0, plus = 0, append = 0, fd; + if (!mode || !mode[0]) { + _impure_ptr->_errno = EINVAL; + return NULL; + } + + if (mode[1] == 'b') { + plus = mode[2] == '+'; + } else if (mode[1]) { + if (mode[1] != '+') { + _impure_ptr->_errno = EINVAL; + return NULL; + } + plus = 1; + } + + switch (mode[0]) { + case 'r': + if (plus) { + flags = O_RDWR; + } else { + flags = O_RDONLY; + } + break; + case 'w': + if (plus) { + flags = O_RDWR | O_CREAT | O_TRUNC; + } else { + flags = O_WRONLY | O_CREAT | O_TRUNC; + } + break; + case 'a': + append = 1; + if (plus) { // won't be properly supported + flags = O_RDWR | O_CREAT; + } else { + flags = O_WRONLY | O_CREAT; + } + break; + default: + _impure_ptr->_errno = EINVAL; + return NULL; + } + + fd = open(fname, flags); + + if (fd >= 0) { + r = (FILE *) malloc(sizeof(FILE)); + r->fd = fd; + } + + return r; +} + +static inline int fclose(FILE * stream) { + int fd; + + if (!stream) { + _impure_ptr->_errno = EINVAL; + return -1; + } + + fd = stream->fd; + free(stream); + return close(fd); +} + +// Again, the compiler should do the right thing, and optimize depending on the values of size and nmemb. +// Luckily, we always will get into the short cases. +static inline size_t fread(void * _ptr, size_t size, size_t nmemb, FILE * stream) { + int i; + uint8_t * ptr = (uint8_t *) _ptr; + + if (!stream) { + _impure_ptr->_errno = EINVAL; + return -1; + } + + if (size == 1) + return read(stream->fd, ptr, nmemb); + + if (nmemb == 1) + return read(stream->fd, ptr, size) == size ? 1 : 0; + + for (i = 0; i < nmemb; i++) { + if (read(stream->fd, ptr + size * i, size) != size) + return i; + } + + return nmemb; +} + +static inline size_t fwrite(const void * _ptr, size_t size, size_t nmemb, FILE * stream) { + int i; + const uint8_t * ptr = (const uint8_t *) _ptr; + + if (!stream) { + _impure_ptr->_errno = EINVAL; + return -1; + } + + if (size == 1) + return write(stream->fd, ptr, nmemb); + + if (nmemb == 1) + return write(stream->fd, ptr, size) == size ? 1 : 0; + + for (i = 0; i < nmemb; i++) { + if (write(stream->fd, ptr + size * i, size) != size) + return i; + } + + return nmemb; +} + +extern FILE * stdin, * stdout, * stderr; + +#endif diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h new file mode 100644 index 0000000..1cfe6c4 --- /dev/null +++ b/libc/include/stdlib.h @@ -0,0 +1,12 @@ +#ifndef __STDLIB_H__ +#define __STDLIB_H__ + +#include +#include + +typedef void (*atexit_func_t)(void); + +void exit(int status) __attribute__((noreturn)); +int atexit(atexit_func_t); + +#endif diff --git a/libc/include/string.h b/libc/include/string.h new file mode 100644 index 0000000..2ec2a84 --- /dev/null +++ b/libc/include/string.h @@ -0,0 +1,97 @@ +#ifndef __STRING_H__ +#define __STRING_H__ + +#include +#include + +static inline void * memcpy(void * _s1, const void * _s2, size_t n) { + uint8_t * s1 = (uint8_t *) _s1; + const uint8_t * s2 = (uint8_t *) _s2; + size_t i; + + for (i = 0; i < n; i++) + *s1++ = *s2++; + + return _s1; +} + +static inline int memcmp(const void * _s1, const void * _s2, size_t n) { + uint8_t * s1 = (uint8_t *) _s1; + const uint8_t * s2 = (uint8_t *) _s2; + size_t i; + + for (i = 0; i < n; i++, s1++, s2++) { + if (*s1 < *s2) { + return -1; + } else if (*s1 > *s2) { + return 1; + } + } + + return 0; +} + +static inline void * memset(void * _s, int c, size_t n) { + uint8_t * s = (uint8_t *) _s; + size_t i; + + for (i = 0; i < n; i++) + *s++ = (uint8_t) c; + + return _s; +} + +static inline char * strcat(char * s1, const char * s2) { + char * r = s1; + + while (*s1) + s1++; + + while (*s2) + *s1++ = *s2++; + + *s1 = 0; + + return r; +} + +static inline char * strcpy(char * s1, const char * s2) { + char * r = s1; + + while ((*s1++ = *s2++)); + + return r; +} + +static inline char * strncpy(char * s1, const char * s2, size_t n) { + char * r = s1; + size_t i; + + for (i = 0; i < n; i++) { + if (*s2) { + *s1++ = *s2++; + } else { + *s1++ = 0; + } + } + + return r; +} + +static inline const char * strchr(const char * s, char c) { + while (*s) + if (*s++ == c) + return s; + return NULL; +} + +static inline size_t strlen(const char * s) { + size_t r = 0; + + while (*s++) + r++; + + return r; +} + +#endif diff --git a/libc/include/unistd.h b/libc/include/unistd.h new file mode 100644 index 0000000..8efd838 --- /dev/null +++ b/libc/include/unistd.h @@ -0,0 +1,31 @@ +#ifndef __UNISTD_H__ +#define __UNISTD_H__ + +#include +#include +#include + +typedef int32_t ssize_t; +typedef int32_t off_t; + +enum open_types_t { + O_RDONLY = 0, + O_WRONLY = 1, + O_RDWR = 2, + O_CREAT = 4, + O_TRUNC = 8, + O_APPEND = 16, +}; + +enum seek_wheels_t { + SEEK_SET = 0, + SEEK_CUR = 1, + SEEK_END = 2, +}; + +int open(const char *pathname, int flags); +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); + +#endif -- cgit v1.2.3