1 /*
2 * Copyright (c) 2013 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23 #include <io_handle.h>
24 #include <printf.h>
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <sys/types.h>
29
30 #if LK_LIBC_IMPLEMENTATION_IS_LK
31 #define DEFINE_STDIO_DESC(id) \
32 [(id)] = { \
33 .io = &console_io, \
34 }
35
36 __WEAK FILE __stdio_FILEs[3] = {
37 DEFINE_STDIO_DESC(0), /* stdin */
38 DEFINE_STDIO_DESC(1), /* stdout */
39 DEFINE_STDIO_DESC(2), /* stderr */
40 };
41 #undef DEFINE_STDIO_DESC
42 #endif
43
lock_write_commit_unlock(FILE * fp,const char * s,size_t length)44 static size_t lock_write_commit_unlock(FILE *fp, const char* s, size_t length)
45 {
46 size_t bytes_written;
47 io_handle_t *io = file_io_handle(fp);
48 io_lock(io);
49 bytes_written = io_write(io, s, length);
50 io_write_commit(io);
51 io_unlock(io);
52 return bytes_written;
53 }
54
fputc(int _c,FILE * fp)55 int fputc(int _c, FILE *fp)
56 {
57 unsigned char c = _c;
58 return lock_write_commit_unlock(fp, (char *)&c, 1);
59 }
60
putchar(int c)61 int putchar(int c)
62 {
63 return fputc(c, stdout);
64 }
65
puts(const char * str)66 int puts(const char *str)
67 {
68 int err = fputs(str, stdout);
69 if (err >= 0)
70 err = fputc('\n', stdout);
71 return err;
72 }
73
fputs(const char * s,FILE * fp)74 int fputs(const char *s, FILE *fp)
75 {
76 size_t len = strlen(s);
77 return lock_write_commit_unlock(fp, s, len);
78 }
79
fwrite(const void * ptr,size_t size,size_t count,FILE * fp)80 size_t fwrite(const void *ptr, size_t size, size_t count, FILE *fp)
81 {
82 size_t bytes_written;
83
84 if (size == 0 || count == 0)
85 return 0;
86
87 // fast path for size == 1
88 if (likely(size == 1)) {
89 return lock_write_commit_unlock(fp, ptr, count);
90 }
91
92 bytes_written = lock_write_commit_unlock(fp, ptr, size * count);
93 return bytes_written / size;
94 }
95
getc(FILE * fp)96 int getc(FILE *fp)
97 {
98 char c;
99 io_handle_t *io = file_io_handle(fp);
100 ssize_t ret = io_read(io, &c, sizeof(c));
101
102 return (ret > 0) ? c : ret;
103 }
104
getchar(void)105 int getchar(void)
106 {
107 return getc(stdin);
108 }
109
_fprintf_output_func(const char * str,size_t len,void * state)110 static int _fprintf_output_func(const char *str, size_t len, void *state)
111 {
112 io_handle_t *io = file_io_handle((FILE *)state);
113
114 return io_write(io, str, len);
115 }
116
vfprintf_worker(FILE * fp,const char * fmt,va_list ap,int filtered_on_release)117 int vfprintf_worker(FILE *fp, const char *fmt, va_list ap, int filtered_on_release)
118 {
119 io_handle_t *io = file_io_handle(fp);
120 io_lock(io);
121 int result = _printf_engine(&_fprintf_output_func, (void *)fp, fmt, ap);
122 io_write_commit(io);
123 io_unlock(io);
124 return result;
125 }
126
fprintf(FILE * fp,const char * fmt,...)127 int fprintf(FILE *fp, const char *fmt, ...)
128 {
129 va_list ap;
130 int err;
131
132 va_start(ap, fmt);
133 err = vfprintf(fp, fmt, ap);
134 va_end(ap);
135 return err;
136 }
137
printf(const char * fmt,...)138 int printf(const char *fmt, ...)
139 {
140 #if DISABLE_DEBUG_OUTPUT
141 return 0;
142 #else
143 va_list ap;
144 int err;
145
146 va_start(ap, fmt);
147 err = vfprintf(stdout, fmt, ap);
148 va_end(ap);
149
150 return err;
151 #endif
152 }
153
vprintf(const char * fmt,va_list ap)154 int vprintf(const char *fmt, va_list ap)
155 {
156 #if DISABLE_DEBUG_OUTPUT
157 return 0;
158 #else
159 return vfprintf(stdout, fmt, ap);
160 #endif
161 }
162
163 #if LK_LIBC_IMPLEMENTATION_IS_LK
fflush(FILE * stream)164 int fflush(FILE *stream) {
165 /* nothing to flush; output streams aren't buffered */
166 return 0;
167 }
168 #endif
169