aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDima Zavin <dima@android.com>2013-06-13 12:29:47 -0700
committerDima Zavin <dima@android.com>2013-08-05 10:04:29 -0700
commit6150422ff5c85fa0f90075889af809c023a21adb (patch)
tree299de0e3ed7d0185d0fa4d0549e347aea77b2358
parent36c77355330cd4f1f4767f4319d81b59623afd10 (diff)
downloadlk-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.h14
-rw-r--r--lib/debug/debug.c43
-rw-r--r--lib/libc/stdio.c21
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;