stdio: fread() and fwrite
[neatlibc.git] / stdio.c
blob83b2429f63a195033328b4aabadd6f814c8a160d
1 #include <ctype.h>
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <stdarg.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
10 #define BUFSZ 1024
12 static char _ibuf[BUFSZ], _obuf[BUFSZ], _ebuf[BUFSZ];
13 static FILE _stdin = {0, EOF, _ibuf, NULL, BUFSZ, 0};
14 static FILE _stdout = {1, EOF, NULL, _obuf, 0, BUFSZ};
15 static FILE _stderr = {2, EOF, NULL, _ebuf, 0, 1};
16 FILE *stdin = &_stdin;
17 FILE *stdout = &_stdout;
18 FILE *stderr = &_stderr;
20 FILE *fopen(char *path, char *mode)
22 FILE *fp;
23 int flags;
25 if (strchr(mode, '+'))
26 flags = O_RDWR;
27 else
28 flags = *mode == 'r' ? O_RDONLY : O_WRONLY;
29 if (*mode != 'r')
30 flags |= O_CREAT;
31 if (*mode == 'w')
32 flags |= O_TRUNC;
33 if (*mode == 'a')
34 flags |= O_APPEND;
36 fp = malloc(sizeof(*fp));
37 memset(fp, 0, sizeof(*fp));
38 fp->fd = open(path, flags, 0600);
39 if (fp->fd < 0) {
40 free(fp);
41 return NULL;
43 fp->back = EOF;
44 fp->ibuf = malloc(BUFSZ);
45 fp->obuf = malloc(BUFSZ);
46 fp->isize = BUFSZ;
47 fp->osize = BUFSZ;
48 fp->iown = 1;
49 fp->oown = 1;
50 return fp;
53 int fclose(FILE *fp)
55 int ret = close(fp->fd);
56 if (fp->iown)
57 free(fp->ibuf);
58 if (fp->oown)
59 free(fp->obuf);
60 free(fp);
61 return ret;
64 int fflush(FILE *fp)
66 if (fp->fd < 0)
67 return 0;
68 if (write(fp->fd, fp->obuf, fp->olen) != fp->olen)
69 return EOF;
70 fp->olen = 0;
71 return 0;
74 static int oc(FILE *fp, int c)
76 if (fp->olen < fp->osize) {
77 fp->obuf[fp->olen++] = c;
78 fp->ostat++;
80 if (c == '\n' || fp->olen == fp->osize)
81 if (fflush(fp))
82 return EOF;
83 return c;
86 static void ostr(FILE *fp, char *s, int wid)
88 int fill = wid - strlen(s);
89 while (fill-- > 0)
90 oc(fp, ' ');
91 while (*s)
92 oc(fp, (unsigned char) *s++);
95 static int digits(unsigned long n, int base)
97 int i;
98 for (i = 0; n; i++)
99 n /= base;
100 return i ? i : 1;
103 static char *digs = "0123456789abcdef";
105 static void oint(FILE *fp, unsigned long n, int base, int sign,
106 int wid, int fill, int psign, int bytes)
108 char buf[64];
109 char *s = buf;
110 int neg = 0;
111 int d;
112 int i;
113 if (sign && (signed long) n < 0) {
114 neg = 1;
115 n = -n;
117 if (bytes == 1)
118 n &= 0x000000ff;
119 if (bytes == 2)
120 n &= 0x0000ffff;
121 if (bytes == 4)
122 n &= 0xffffffff;
123 d = digits(n, base);
124 for (i = 0; i < d; i++) {
125 s[d - i - 1] = digs[n % base];
126 n /= base;
128 s[d] = '\0';
129 for (i = d + neg; i < wid; i++)
130 oc(fp, fill);
131 if (neg || psign)
132 oc(fp, neg ? '-' : '+');
133 ostr(fp, buf, 0);
136 int vfprintf(FILE *fp, char *fmt, va_list ap)
138 char *s = fmt;
139 int beg = fp->ostat;
140 while (*s) {
141 int c = (unsigned char) *s++;
142 int fill = ' ';
143 int wid = 0;
144 int psign = 0; /* add sign as in %+d */
145 int bytes = sizeof(int);
146 if (c != '%') {
147 oc(fp, c);
148 continue;
150 if (*s == '0') {
151 fill = '0';
152 s++;
154 while (isdigit(*s)) {
155 wid *= 10;
156 wid += *s++ - '0';
158 if (*s == '+') {
159 psign = 1;
160 s++;
162 while (*s == 'l') {
163 bytes = sizeof(long);
164 s++;
166 while (*s == 'h') {
167 bytes = bytes < sizeof(int) ? sizeof(char) : sizeof(short);
168 s++;
170 switch ((c = *s++)) {
171 case 'd':
172 oint(fp, va_arg(ap, long), 10, 1, wid, fill, psign, bytes);
173 break;
174 case 'u':
175 oint(fp, va_arg(ap, long), 10, 0, wid, fill, 0, bytes);
176 break;
177 case 'x':
178 case 'p':
179 oint(fp, va_arg(ap, long), 16, 0, wid, fill, 0, bytes);
180 break;
181 case 'c':
182 oc(fp, va_arg(ap, int));
183 break;
184 case 's':
185 ostr(fp, va_arg(ap, char *), wid);
186 break;
187 case '\0':
188 s--;
189 break;
190 default:
191 oc(fp, c);
194 return fp->ostat - beg;
197 void perror(char *s)
199 int idx = errno;
200 if (idx >= sys_nerr)
201 idx = 0;
202 fprintf(stderr, "%s: %s\n", s, sys_errlist[idx]);
205 int vsnprintf(char *dst, int sz, char *fmt, va_list ap)
207 FILE f = {-1, EOF};
208 int ret;
209 f.obuf = dst;
210 f.osize = sz - 1;
211 ret = vfprintf(&f, fmt, ap);
212 dst[f.olen] = '\0';
213 return ret;
216 int vsprintf(char *dst, char *fmt, va_list ap)
218 return vsnprintf(dst, 1 << 20, fmt, ap);
221 int printf(char *fmt, ...)
223 va_list ap;
224 int ret;
225 va_start(ap, fmt);
226 ret = vfprintf(stdout, fmt, ap);
227 va_end(ap);
228 return ret;
231 int vprintf(char *fmt, va_list ap)
233 return vfprintf(stdout, fmt, ap);
236 int fprintf(FILE *fp, char *fmt, ...)
238 va_list ap;
239 int ret;
240 va_start(ap, fmt);
241 ret = vfprintf(fp, fmt, ap);
242 va_end(ap);
243 return ret;
246 int sprintf(char *dst, char *fmt, ...)
248 va_list ap;
249 int ret;
250 va_start(ap, fmt);
251 ret = vsprintf(dst, fmt, ap);
252 va_end(ap);
253 return ret;
256 int snprintf(char *dst, int sz, char *fmt, ...)
258 va_list ap;
259 int ret;
260 va_start(ap, fmt);
261 ret = vsnprintf(dst, sz, fmt, ap);
262 va_end(ap);
263 return ret;
266 int fputs(char *s, FILE *fp)
268 while (*s)
269 oc(fp, (unsigned char) *s++);
270 return 0;
273 int puts(char *s)
275 int ret = fputs(s, stdout);
276 if (ret >= 0)
277 oc(stdout, '\n');
278 return ret;
281 long fwrite(void *v, long sz, long n, FILE *fp)
283 unsigned char *s = v;
284 int i = n * sz;
285 while (i-- > 0)
286 if (oc(fp, *s++) == EOF)
287 return n * sz - i - 1;
288 return n * sz;