regex: updates from neatvi
[neatlibc.git] / stdio.c
blob18e23c00815f6a3d2abe357c116a672fda737358
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 int fputc(int c, FILE *fp)
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 int putchar(int c)
88 return fputc(c, stdout);
91 static void ostr(FILE *fp, char *s, int wid, int left)
93 int fill = wid - strlen(s);
94 if (!left)
95 while (fill-- > 0)
96 fputc(' ', fp);
97 while (*s)
98 fputc((unsigned char) *s++, fp);
99 if (left)
100 while (fill-- > 0)
101 fputc(' ', fp);
104 static int digits(unsigned long n, int base)
106 int i;
107 for (i = 0; n; i++)
108 n /= base;
109 return i ? i : 1;
112 static char *digs = "0123456789abcdef";
113 static char *digs_uc = "0123456789ABCDEF";
115 #define FMT_LEFT 0001 /* flag '-' */
116 #define FMT_PLUS 0002 /* flag '+' */
117 #define FMT_BLANK 0004 /* flag ' ' */
118 #define FMT_ALT 0010 /* flag '#' */
119 #define FMT_ZERO 0020 /* flag '0' */
120 #define FMT_SIGNED 0040 /* is the conversion signed? */
121 #define FMT_UCASE 0100 /* uppercase hex digits? */
123 static void oint(FILE *fp, unsigned long n, int base,
124 int wid, int bytes, int flags)
126 char buf[64];
127 char *s = buf;
128 int neg = 0;
129 int sign = '\0';
130 char fill;
131 int left = flags & FMT_LEFT;
132 int alt_form = flags & FMT_ALT;
133 int ucase = flags & FMT_UCASE;
134 int prefix_len = 0; /* length of sign or base prefix */
135 int d;
136 int i;
137 if (flags & FMT_SIGNED) {
138 if ((signed long) n < 0) {
139 neg = 1;
140 sign = '-';
141 n = -n;
142 } else {
143 if (flags & FMT_PLUS)
144 sign = '+';
145 else if (flags & FMT_BLANK)
146 sign = ' ';
148 prefix_len = !!sign;
149 } else if (n > 0 && alt_form) {
150 prefix_len = base == 16 ? 2 : 1;
152 if (bytes == 1)
153 n &= 0x000000ff;
154 if (bytes == 2)
155 n &= 0x0000ffff;
156 if (bytes == 4)
157 n &= 0xffffffff;
158 d = digits(n, base);
159 for (i = 0; i < d; i++) {
160 s[d - i - 1] = ucase ? digs_uc[n % base] : digs[n % base];
161 n /= base;
163 s[d] = '\0';
164 fill = (flags & FMT_ZERO) ? '0' : ' ';
165 i = d + prefix_len;
166 if (fill == ' ' && !left)
167 while (i++ < wid)
168 fputc(' ', fp);
169 if (sign) {
170 fputc(sign, fp);
171 } else if (prefix_len) {
172 fputc('0', fp);
173 if (base == 16)
174 fputc(ucase ? 'X' : 'x', fp);
176 if (fill == '0' && !left)
177 while (i++ < wid)
178 fputc('0', fp);
179 ostr(fp, buf, 0, 0);
180 if (left)
181 while (i++ < wid)
182 fputc(' ', fp);
185 static char *fmt_flags = "-+ #0";
187 int vfprintf(FILE *fp, char *fmt, va_list ap)
189 char *s = fmt;
190 int beg = fp->ostat;
191 while (*s) {
192 int c = (unsigned char) *s++;
193 int wid = 0;
194 int bytes = sizeof(int);
195 int flags = 0;
196 int left;
197 char *f;
198 if (c != '%') {
199 fputc(c, fp);
200 continue;
202 while ((f = strchr(fmt_flags, *s))) {
203 flags |= 1 << (f - fmt_flags);
204 s++;
206 left = flags & FMT_LEFT;
207 if (*s == '*') {
208 wid = va_arg(ap, int);
209 if (wid < 0) {
210 flags |= FMT_LEFT;
211 wid = -wid;
213 s++;
214 } else {
215 while (isdigit(*s)) {
216 wid *= 10;
217 wid += *s++ - '0';
220 while (*s == 'l') {
221 bytes = sizeof(long);
222 s++;
224 while (*s == 'h') {
225 bytes = bytes < sizeof(int) ? sizeof(char) : sizeof(short);
226 s++;
228 switch ((c = *s++)) {
229 case 'd': case 'i':
230 flags |= FMT_SIGNED;
231 oint(fp, va_arg(ap, long), 10, wid, bytes, flags);
232 break;
233 case 'u':
234 flags &= ~FMT_ALT;
235 oint(fp, va_arg(ap, long), 10, wid, bytes, flags);
236 break;
237 case 'o':
238 oint(fp, va_arg(ap, long), 8, wid, bytes, flags);
239 break;
240 case 'p':
241 flags |= FMT_ALT;
242 case 'x':
243 oint(fp, va_arg(ap, long), 16, wid, bytes, flags);
244 break;
245 case 'X':
246 flags |= FMT_UCASE;
247 oint(fp, va_arg(ap, long), 16, wid, bytes, flags);
248 break;
249 case 'c':
250 if (left)
251 fputc(va_arg(ap, int), fp);
252 while (wid-- > 1)
253 fputc(' ', fp);
254 if (!left)
255 fputc(va_arg(ap, int), fp);
256 break;
257 case 's':
258 ostr(fp, va_arg(ap, char *), wid, left);
259 break;
260 case 'n':
261 *va_arg(ap, int *) = fp->ostat - beg;
262 break;
263 case '\0':
264 s--;
265 break;
266 default:
267 fputc(c, fp);
270 return fp->ostat - beg;
273 void perror(char *s)
275 int idx = errno;
276 if (idx >= sys_nerr)
277 idx = 0;
278 if (s && *s)
279 fprintf(stderr, "%s: %s\n", s, sys_errlist[idx]);
280 else
281 fprintf(stderr, "%s\n", sys_errlist[idx]);
284 int vsnprintf(char *dst, int sz, char *fmt, va_list ap)
286 FILE f = {-1, EOF};
287 int ret;
288 f.obuf = dst;
289 f.osize = sz - 1;
290 ret = vfprintf(&f, fmt, ap);
291 dst[f.olen] = '\0';
292 return ret;
295 int vsprintf(char *dst, char *fmt, va_list ap)
297 return vsnprintf(dst, 1 << 20, fmt, ap);
300 int printf(char *fmt, ...)
302 va_list ap;
303 int ret;
304 va_start(ap, fmt);
305 ret = vfprintf(stdout, fmt, ap);
306 va_end(ap);
307 return ret;
310 int vprintf(char *fmt, va_list ap)
312 return vfprintf(stdout, fmt, ap);
315 int fprintf(FILE *fp, char *fmt, ...)
317 va_list ap;
318 int ret;
319 va_start(ap, fmt);
320 ret = vfprintf(fp, fmt, ap);
321 va_end(ap);
322 return ret;
325 int sprintf(char *dst, char *fmt, ...)
327 va_list ap;
328 int ret;
329 va_start(ap, fmt);
330 ret = vsprintf(dst, fmt, ap);
331 va_end(ap);
332 return ret;
335 int snprintf(char *dst, int sz, char *fmt, ...)
337 va_list ap;
338 int ret;
339 va_start(ap, fmt);
340 ret = vsnprintf(dst, sz, fmt, ap);
341 va_end(ap);
342 return ret;
345 int fputs(char *s, FILE *fp)
347 while (*s)
348 fputc((unsigned char) *s++, fp);
349 return 0;
352 int puts(char *s)
354 int ret = fputs(s, stdout);
355 if (ret >= 0)
356 fputc('\n', stdout);
357 return ret;
360 long fwrite(void *v, long sz, long n, FILE *fp)
362 unsigned char *s = v;
363 int i = n * sz;
364 while (i-- > 0)
365 if (fputc(*s++, fp) == EOF)
366 return n * sz - i - 1;
367 return n * sz;