stdlib.h: add labs()
[neatlibc.git] / stdio.c
blob14f52f4065b0b4a65e68426aea2c4b2512eff4cb
1 #include <errno.h>
2 #include <fcntl.h>
3 #include <stdarg.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
9 #define BUFSZ 1024
11 static char _ibuf[BUFSZ], _obuf[BUFSZ], _ebuf[BUFSZ];
12 static FILE _stdin = {0, EOF, _ibuf, NULL, BUFSZ, 0};
13 static FILE _stdout = {1, EOF, NULL, _obuf, 0, BUFSZ};
14 static FILE _stderr = {2, EOF, NULL, _ebuf, 0, 1};
15 FILE *stdin = &_stdin;
16 FILE *stdout = &_stdout;
17 FILE *stderr = &_stderr;
19 FILE *fopen(char *path, char *mode)
21 FILE *fp;
22 int flags;
24 if (strchr(mode, '+'))
25 flags = O_RDWR;
26 else
27 flags = *mode == 'r' ? O_RDONLY : O_WRONLY;
28 if (*mode != 'r')
29 flags |= O_CREAT;
30 if (*mode == 'w')
31 flags |= O_TRUNC;
32 if (*mode == 'a')
33 flags |= O_APPEND;
35 fp = malloc(sizeof(*fp));
36 memset(fp, 0, sizeof(*fp));
37 fp->fd = open(path, flags, 0600);
38 if (fp->fd < 0) {
39 free(fp);
40 return NULL;
42 fp->back = EOF;
43 fp->ibuf = malloc(BUFSZ);
44 fp->obuf = malloc(BUFSZ);
45 fp->isize = BUFSZ;
46 fp->osize = BUFSZ;
47 fp->iown = 1;
48 fp->oown = 1;
49 return fp;
52 int fclose(FILE *fp)
54 int ret = close(fp->fd);
55 if (fp->iown)
56 free(fp->ibuf);
57 if (fp->oown)
58 free(fp->obuf);
59 free(fp);
60 return ret;
63 int fflush(FILE *fp)
65 if (fp->fd < 0)
66 return 0;
67 if (write(fp->fd, fp->obuf, fp->olen) != fp->olen)
68 return EOF;
69 fp->olen = 0;
70 return 0;
73 static int oc(FILE *fp, int c)
75 if (fp->olen < fp->osize) {
76 fp->obuf[fp->olen++] = c;
77 fp->ostat++;
79 if (c == '\n' || fp->olen == fp->osize)
80 fflush(fp);
81 return c;
84 static void ostr(FILE *fp, char *s, int wid)
86 int fill = wid - strlen(s);
87 while (fill-- > 0)
88 oc(fp, ' ');
89 while (*s)
90 oc(fp, *s++);
93 static int digits(unsigned long n, int base)
95 int i;
96 for (i = 0; n; i++)
97 n /= base;
98 return i ? i : 1;
101 static char *digs = "0123456789abcdef";
103 static void oint(FILE *fp, unsigned long n, int base, int sign, int wid, int fill)
105 char buf[64];
106 char *s = buf;
107 int neg = 0;
108 int d;
109 int i;
110 if (sign && (signed long) n < 0) {
111 neg = 1;
112 n = -n;
114 d = digits(n, base);
115 for (i = 0; i < d; i++) {
116 s[d - i - 1] = digs[n % base];
117 n /= base;
119 s[d] = '\0';
120 for (i = d + neg; i < wid; i++)
121 oc(fp, fill);
122 if (neg)
123 oc(fp, '-');
124 ostr(fp, buf, 0);
127 int vfprintf(FILE *fp, char *fmt, va_list ap)
129 char *s = fmt;
130 int beg = fp->ostat;
131 while (*s) {
132 int c = *s++;
133 int fill = ' ';
134 int wid = 0;
135 if (c != '%') {
136 oc(fp, c);
137 continue;
139 if (*s == 'l')
140 s++;
141 if (*s == '0') {
142 fill = '0';
143 s++;
145 while (isdigit(*s)) {
146 wid *= 10;
147 wid += *s++ - '0';
149 switch ((c = *s++)) {
150 case 'd':
151 oint(fp, va_arg(ap, long), 10, 1, wid, fill);
152 break;
153 case 'u':
154 oint(fp, va_arg(ap, long), 10, 0, wid, fill);
155 break;
156 case 'x':
157 case 'p':
158 oint(fp, va_arg(ap, long), 16, 0, wid, fill);
159 break;
160 case 'c':
161 oc(fp, va_arg(ap, int));
162 break;
163 case 's':
164 ostr(fp, va_arg(ap, char *), wid);
165 break;
166 case '\0':
167 s--;
168 break;
169 default:
170 oc(fp, c);
173 return fp->ostat - beg;
176 void perror(char *s)
178 int idx = errno;
179 if (idx >= sys_nerr)
180 idx = 0;
181 fprintf(stderr, "%s: %s\n", s, sys_errlist[idx]);
184 int vsnprintf(char *dst, int sz, char *fmt, va_list ap)
186 FILE f = {-1, EOF};
187 int ret;
188 f.obuf = dst;
189 f.osize = sz - 1;
190 ret = vfprintf(&f, fmt, ap);
191 dst[f.olen] = '\0';
192 return ret;
195 int vsprintf(char *dst, char *fmt, va_list ap)
197 return vsnprintf(dst, 1 << 20, fmt, ap);
200 int printf(char *fmt, ...)
202 va_list ap;
203 int ret;
204 va_start(ap, fmt);
205 ret = vfprintf(stdout, fmt, ap);
206 va_end(ap);
207 return ret;
210 int fprintf(FILE *fp, char *fmt, ...)
212 va_list ap;
213 int ret;
214 va_start(ap, fmt);
215 ret = vfprintf(fp, fmt, ap);
216 va_end(ap);
217 return ret;
220 int sprintf(char *dst, char *fmt, ...)
222 va_list ap;
223 int ret;
224 va_start(ap, fmt);
225 ret = vsprintf(dst, fmt, ap);
226 va_end(ap);
227 return ret;
230 int snprintf(char *dst, int sz, char *fmt, ...)
232 va_list ap;
233 int ret;
234 va_start(ap, fmt);
235 ret = vsnprintf(dst, sz, fmt, ap);
236 va_end(ap);
237 return ret;