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/stdio.h | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 libc/include/stdio.h (limited to 'libc/include/stdio.h') 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 -- cgit v1.2.3