diff options
author | Dima Zavin <dima@android.com> | 2013-06-13 12:29:47 -0700 |
---|---|---|
committer | Dima Zavin <dima@android.com> | 2013-08-05 10:04:29 -0700 |
commit | 6150422ff5c85fa0f90075889af809c023a21adb (patch) | |
tree | 299de0e3ed7d0185d0fa4d0549e347aea77b2358 | |
parent | 36c77355330cd4f1f4767f4319d81b59623afd10 (diff) | |
download | lk-6150422ff5c85fa0f90075889af809c023a21adb.tar.gz |
[lib][stdio] implement a real FILE backing stdio descriptors
Allows different implementations of FILE handling to be provided.
Make lib/debug provide the default implementation for
stdin/stdout/stderr.
Change-Id: Icd9d30ac44884648603e91cfca856912bca1c0d3
Signed-off-by: Dima Zavin <dima@android.com>
-rw-r--r-- | include/stdio.h | 14 | ||||
-rw-r--r-- | lib/debug/debug.c | 43 | ||||
-rw-r--r-- | lib/libc/stdio.c | 21 |
3 files changed, 60 insertions, 18 deletions
diff --git a/include/stdio.h b/include/stdio.h index 75cd3723..ce9c548b 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -29,13 +29,19 @@ __BEGIN_CDECLS -/* fake FILE struct */ typedef struct FILE { + void *ctx; + int (*fputc)(void *ctx, int c); + int (*fputs)(void *ctx, const char *s); + int (*fgetc)(void *ctx); + int (*vfprintf)(void *ctx, const char *fmt, va_list ap); } FILE; -#define stdin ((FILE *)1) -#define stdout ((FILE *)2) -#define stderr ((FILE *)3) +extern FILE __stdio_FILEs[]; + +#define stdin (&__stdio_FILEs[0]) +#define stdout (&__stdio_FILEs[1]) +#define stderr (&__stdio_FILEs[2]) FILE *fopen(const char *filename, const char *mode); int fclose(FILE *stream); diff --git a/lib/debug/debug.c b/lib/debug/debug.c index bf2777e8..761195cf 100644 --- a/lib/debug/debug.c +++ b/lib/debug/debug.c @@ -59,6 +59,49 @@ void _panic(void *caller, const char *fmt, ...) halt(); } +static int __debug_stdio_fputc(void *ctx, int c) +{ + _dputc(c); + return 0; +} + +static int __debug_stdio_fputs(void *ctx, const char *s) +{ + return _dputs(s); +} + +static int __debug_stdio_fgetc(void *ctx) +{ + char c; + int err; + + err = platform_dgetc(&c, true); + if (err < 0) + return err; + return (unsigned char)c; +} + +static int __debug_stdio_vfprintf(void *ctx, const char *fmt, va_list ap) +{ + return _dvprintf(fmt, ap); +} + +#define DEFINE_STDIO_DESC(id) \ + [(id)] = { \ + .ctx = &__stdio_FILEs[(id)], \ + .fputc = __debug_stdio_fputc, \ + .fputs = __debug_stdio_fputs, \ + .fgetc = __debug_stdio_fgetc, \ + .vfprintf = __debug_stdio_vfprintf, \ + } + +FILE __stdio_FILEs[3] = { + DEFINE_STDIO_DESC(0), /* stdin */ + DEFINE_STDIO_DESC(1), /* stdout */ + DEFINE_STDIO_DESC(2), /* stderr */ +}; +#undef DEFINE_STDIO_DESC + #if !DISABLE_DEBUG_OUTPUT int _dputs(const char *str) diff --git a/lib/libc/stdio.c b/lib/libc/stdio.c index a65b30b5..698700b8 100644 --- a/lib/libc/stdio.c +++ b/lib/libc/stdio.c @@ -28,8 +28,7 @@ int fputc(int c, FILE *fp) { - _dputc(c); - return 0; + return fp->fputc(fp->ctx, c); } int putchar(int c) @@ -39,27 +38,20 @@ int putchar(int c) int puts(const char *str) { - int err = _dputs(str); + int err = fputs(str, stdout); if (err >= 0) - _dputc('\n'); - + err = fputc('\n', stdout); return err; } int fputs(const char *s, FILE *fp) { - return _dputs(s); + return fp->fputs(fp->ctx, s); } int getc(FILE *fp) { - char c; - - int err = platform_dgetc(&c, true); - if (err < 0) - return err; - - return (unsigned char)c; + return fp->fgetc(fp->ctx); } int getchar(void) @@ -70,10 +62,11 @@ int getchar(void) int _printf(const char *fmt, ...) { int err; + FILE *fp = stdout; va_list ap; va_start(ap, fmt); - err = _dvprintf(fmt, ap); + err = fp->vfprintf(fp->ctx, fmt, ap); va_end(ap); return err; |