From a8423321b802bff39fe2ba22f2b0a26220a57535 Mon Sep 17 00:00:00 2001 From: Marcin Bukat Date: Fri, 18 Jan 2013 16:16:59 +0100 Subject: stdio compat layer for plugins This is attempt to simplify porting programs to rockbox (as plugins). Currently this compat layer implements: fopen(), fclose(), fflush(), fread(), fwrite(), fseek(), fseeko(), ftell(), ftello(), fgetc(), ungetc(), fputc(), fgets(), clearerr(), ferror(), feof(), fprintf() In order to use it you need to include in ported sources "lib/stdio_compat.h" Change-Id: I5add615dd19c5af9c767ccbfb1bd5a4e466741cb --- apps/plugins/lib/SOURCES | 1 + apps/plugins/lib/stdio_compat.c | 231 ++++++++++++++++++++++++++++++++++++++++ apps/plugins/lib/stdio_compat.h | 67 ++++++++++++ firmware/libc/include/stdint.h | 2 + 4 files changed, 301 insertions(+) create mode 100644 apps/plugins/lib/stdio_compat.c create mode 100644 apps/plugins/lib/stdio_compat.h diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES index 747355b44b..9a7aef51d0 100644 --- a/apps/plugins/lib/SOURCES +++ b/apps/plugins/lib/SOURCES @@ -11,6 +11,7 @@ highscore.c simple_viewer.c display_text.c strncpy.c +stdio_compat.c #if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) grey_core.c diff --git a/apps/plugins/lib/stdio_compat.c b/apps/plugins/lib/stdio_compat.c new file mode 100644 index 0000000000..d2b8f9bbc7 --- /dev/null +++ b/apps/plugins/lib/stdio_compat.c @@ -0,0 +1,231 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2013 by Marcin Bukat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "plugin.h" +#include "stdio_compat.h" + +static _FILE_ __file__[MAX_STDIO_FILES] = { + {-1,-1,0},{-1,-1,0},{-1,-1,0},{-1,-1,0}, + {-1,-1,0},{-1,-1,0},{-1,-1,0},{-1,-1,0} +}; + +_FILE_ *_fopen_(const char *path, const char *mode) +{ + _FILE_ *f = __file__; + int flags = O_RDONLY; + int fd = -1; + int i; + + /* look for free slot */ + for (i=0; ifd == -1) + break; + + /* no empty slots */ + if (i == MAX_STDIO_FILES) + return NULL; + + if (*mode != 'r') + { + /* Not read */ + flags = (O_WRONLY | O_CREAT | O_TRUNC); + if (*mode != 'w') + { + /* Not write (create of append) */ + flags = (O_WRONLY | O_CREAT | O_APPEND); + if (*mode != 'a') + { + /* Illegal */ + return NULL; + } + } + } + + if (mode[1] == 'b') + { + /* Ignore */ + mode++; + } + + if (mode[1] == '+') + { + /* Read and Write. */ + flags |= (O_RDONLY | O_WRONLY); + flags += (O_RDWR - (O_RDONLY | O_WRONLY)); + } + + + fd = rb->open(path, flags); + + if (fd == -1) + return NULL; + + /* initialize */ + f->fd = fd; + f->unget_char = -1; + + return f; +} + +int _fflush_(_FILE_ *stream) +{ + (void)stream; + /* no buffering so we are always in sync */ + return 0; +} + +size_t _fread_(void *ptr, size_t size, size_t nmemb, _FILE_ *stream) +{ + ssize_t ret = rb->read(stream->fd, (char *)ptr, size*nmemb); + + if (ret < (ssize_t)(size*nmemb)) + stream->error = -1; + + return ret; +} + +size_t _fwrite_(const void *ptr, size_t size, size_t nmemb, _FILE_ *stream) +{ + ssize_t ret = rb->write(stream->fd, ptr, size*nmemb); + + if (ret < (ssize_t)(size*nmemb)) + stream->error = -1; + + return ret; +} + +int _fseek_(_FILE_ *stream, long offset, int whence) +{ + return rb->lseek(stream->fd, offset, whence); +} + +long _ftell_(_FILE_ *stream) +{ + return rb->lseek(stream->fd, 0, SEEK_CUR); +} + +int _fclose_(_FILE_ *stream) +{ + if (stream->fd == -1) + return EOF; + + if (rb->close(stream->fd) == -1) + return EOF; + + /* free the resource */ + stream->fd = -1; + + return 0; +} + +int _fgetc_(_FILE_ *stream) +{ + unsigned char c; + + if (stream->unget_char != -1) + { + c = stream->unget_char; + stream->unget_char = -1; + return c; + } + + if ( rb->read(stream->fd, &c, 1) != 1) + return EOF; + + return c; +} + +int _ungetc_(int c, _FILE_ *stream) +{ + stream->unget_char = c; + + return c; +} + +int _fputc_(int c, _FILE_ *stream) +{ + unsigned char cb = c; + + if (rb->write(stream->fd, &cb, 1) != 1) + return EOF; + + return cb; +} + +char *_fgets_(char *s, int size, _FILE_ *stream) +{ + char *p = s; + char c = '\0'; + + for (int i=0; iread(stream->fd, &c, 1) != 1) + break; + + *p++ = c; + + if (c == '\n') + break; + } + + if (p == s) + return NULL; + + *p = '\0'; + + return s; +} + +void _clearerr_(_FILE_ *stream) +{ + if (stream) + stream->error = 0; +} + +int _ferror_(_FILE_ *stream) +{ + return (stream) ? stream->error : -1; +} + +int _feof_(_FILE_ *stream) +{ + int c = _fgetc_(stream); + + if (c != EOF) + { + _ungetc_(c, stream); + return 0; + } + + return 0; +} + +int _fprintf_(_FILE_ *stream, const char *format, ...) +{ + int len; + va_list ap; + char buf[256]; + + va_start(ap, format); + len = rb->vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + return _fwrite_(buf, 1, len, stream); +} diff --git a/apps/plugins/lib/stdio_compat.h b/apps/plugins/lib/stdio_compat.h new file mode 100644 index 0000000000..bb37940296 --- /dev/null +++ b/apps/plugins/lib/stdio_compat.h @@ -0,0 +1,67 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2013 by Marcin Bukat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include + +#define MAX_STDIO_FILES 8 + +#undef FILE +#define FILE _FILE_ + +#define fopen _fopen_ +#define fclose _fclose_ +#define fflush _fflush_ +#define fread _fread_ +#define fwrite _fwrite_ +#define fseek _fseek_ +#define fseeko _fseek_ +#define ftell _ftell_ +#define ftello _ftell_ +#define fgetc _fgetc_ +#define ungetc _ungetc_ +#define fputc _fputc_ +#define fgets _fgets_ +#define clearerr _clearerr_ +#define ferror _ferror_ +#define feof _feof_ +#define fprintf _fprintf_ + +typedef struct { + int fd; + int unget_char; + int error; +} _FILE_; + +_FILE_ *_fopen_(const char *path, const char *mode); +int _fclose_(_FILE_ *stream); +int _fflush_(_FILE_ *stream); +size_t _fread_(void *ptr, size_t size, size_t nmemb, _FILE_ *stream); +size_t _fwrite_(const void *ptr, size_t size, size_t nmemb, _FILE_ *stream); +int _fseek_(_FILE_ *stream, long offset, int whence); +long _ftell_(_FILE_ *stream); +int _fgetc_(_FILE_ *stream); +int _ungetc_(int c, _FILE_ *stream); +int _fputc_(int c, _FILE_ *stream); +char *_fgets_(char *s, int size, _FILE_ *stream); +int _unlink_(const char *pathname); +void _clearerr_(_FILE_ *stream); +int _ferror_(_FILE_ *stream); +int _feof_(_FILE_ *stream); +int _fprintf_(_FILE_ *stream, const char *format, ...); diff --git a/firmware/libc/include/stdint.h b/firmware/libc/include/stdint.h index 93f234c0e8..011c4ab8fc 100644 --- a/firmware/libc/include/stdint.h +++ b/firmware/libc/include/stdint.h @@ -104,4 +104,6 @@ #endif +#define uintmax_t unsigned long long +#define intmax_t long long #endif /* __STDINT_H__ */ -- cgit v1.2.3