uc-sdk
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
stdio.h
Go to the documentation of this file.
1 #ifndef __STDIO_H__
2 #define __STDIO_H__
3 
4 #include <reent.h>
5 #include <stdarg.h>
6 #include <stddef.h>
7 #include <unistd.h>
8 #include <malloc.h>
9 
10 static const int EOF = -1;
11 
12 struct _FILE {
13  int fd;
14  int got_eof;
15 };
16 
17 typedef struct _FILE FILE;
18 extern FILE * stdin, * stdout, * stderr;
19 
20 int vdprintf(int fd, const char * format, va_list ap);
21 int vsprintf(char * str, const char * format, va_list ap);
22 int vsnprintf(char * str, size_t size, const char * format, va_list ap);
23 int vasprintf(char ** strp, const char * format, va_list ap);
24 int vxprintf(void (*func)(const char *, int, void *), void * arg, const char * format, va_list ap);
25 static inline int vfprintf(FILE * stream, const char * format, va_list ap) { return vdprintf(stream->fd, format, ap); }
26 static inline int vprintf(const char * format, va_list ap) { return vfprintf(stdout, format, ap); }
27 
28 static inline int dprintf(int fd, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vdprintf(fd, format, ap); va_end(ap); return r; }
29 static inline int sprintf(char * str, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vsprintf(str, format, ap); va_end(ap); return r; }
30 static inline int snprintf(char * str, size_t size, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vsnprintf(str, size, format, ap); va_end(ap); return r; }
31 static inline int asprintf(char ** strp, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vasprintf(strp, format, ap); va_end(ap); return r; }
32 static inline int xprintf(void (*func)(const char *, int, void *), void * arg, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vxprintf(func, arg, format, ap); va_end(ap); return r; }
33 static inline int fprintf(FILE * stream, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vfprintf(stream, format, ap); va_end(ap); return r; }
34 static inline int printf(const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vprintf(format, ap); va_end(ap); return r; }
35 
36 int vdscanf(int fd, const char * format, va_list ap);
37 int vsscanf(const char * str, const char * format, va_list ap);
38 int vxscanf(int (*xgetc)(void *), void (*xungetc)(void *, int), void * opaque, const char * format, va_list args);
39 static inline int vfscanf(FILE * stream, const char * format, va_list ap) { return vdscanf(stream->fd, format, ap); }
40 static inline int vscanf(const char * format, va_list ap) { return vfscanf(stdin, format, ap); }
41 
42 static inline int dscanf(int fd, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vdscanf(fd, format, ap); va_end(ap); return r; }
43 static inline int sscanf(const char * str, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vsscanf(str, format, ap); va_end(ap); return r; }
44 static inline int xscanf(int (*xgetc)(void *), void (*xungetc)(void *, int), void * opaque, const char *format, ...) { va_list ap; int r; va_start(ap, format); r = vxscanf(xgetc, xungetc, opaque, format, ap); va_end(ap); return r; }
45 static inline int fscanf(FILE * stream, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vfscanf(stream, format, ap); va_end(ap); return r; }
46 static inline int scanf(const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vscanf(format, ap); va_end(ap); return r; }
47 
48 
49 
50 void __sinit(struct _reent *);
51 
52 // We don't even buffer, so...
53 static inline int fflush(FILE *stream) { return 0; }
54 
55 // hopefully, since all of the mode crap is static, gcc will optimize most of it away.
56 static inline FILE * fopen(const char * fname, const char * mode) {
57  FILE * r = NULL;
58  int flags = 0, plus = 0, append = 0, fd;
59  if (!mode || !mode[0]) {
60  set_errno(EINVAL);
61  return NULL;
62  }
63 
64  if (mode[1] == 'b') {
65  plus = mode[2] == '+';
66  } else if (mode[1]) {
67  if (mode[1] != '+') {
68  set_errno(EINVAL);
69  return NULL;
70  }
71  plus = 1;
72  }
73 
74  switch (mode[0]) {
75  case 'r':
76  if (plus) {
77  flags = O_RDWR;
78  } else {
79  flags = O_RDONLY;
80  }
81  break;
82  case 'w':
83  if (plus) {
84  flags = O_RDWR | O_CREAT | O_TRUNC;
85  } else {
86  flags = O_WRONLY | O_CREAT | O_TRUNC;
87  }
88  break;
89  case 'a':
90  append = 1;
91  if (plus) { // won't be properly supported
92  flags = O_RDWR | O_CREAT;
93  } else {
94  flags = O_WRONLY | O_CREAT;
95  }
96  break;
97  default:
98  set_errno(EINVAL);
99  return NULL;
100  }
101 
102  fd = open(fname, flags);
103 
104  if (fd >= 0) {
105  r = (FILE *) malloc(sizeof(FILE));
106  r->fd = fd;
107  r->got_eof = 0;
108  }
109 
110  if (append)
111  lseek(r->fd, 0, SEEK_END);
112 
113  return r;
114 }
115 
116 static inline int fclose(FILE * stream) {
117  int fd;
118 
119  if (!stream) {
120  set_errno(EINVAL);
121  return -1;
122  }
123 
124  fd = stream->fd;
125  free(stream);
126  return close(fd);
127 }
128 
129 // Again, the compiler should do the right thing, and optimize depending on the values of size and nmemb.
130 // Luckily, we always will get into the short cases.
131 static inline size_t fread(void * _ptr, size_t size, size_t nmemb, FILE * stream) {
132  int i;
133  uint8_t * ptr = (uint8_t *) _ptr;
134  size_t r;
135 
136  if (!stream) {
137  set_errno(EINVAL);
138  return -1;
139  }
140 
141  if (size == 1) {
142  r = read(stream->fd, ptr, nmemb);
143  if (r == 0)
144  stream->got_eof = 1;
145  return r;
146  }
147 
148  if (nmemb == 1) {
149  r = read(stream->fd, ptr, size) == size ? 1 : 0;
150  if (r == 0)
151  stream->got_eof = 1;
152  return r;
153  }
154 
155  for (i = 0; i < nmemb; i++) {
156  if (read(stream->fd, ptr + size * i, size) != size) {
157  stream->got_eof = 1;
158  return i;
159  }
160  }
161 
162  return nmemb;
163 }
164 
165 static inline size_t fwrite(const void * _ptr, size_t size, size_t nmemb, FILE * stream) {
166  int i;
167  const uint8_t * ptr = (const uint8_t *) _ptr;
168 
169  if (!stream) {
170  set_errno(EINVAL);
171  return -1;
172  }
173 
174  if (size == 1)
175  return write(stream->fd, ptr, nmemb);
176 
177  if (nmemb == 1)
178  return write(stream->fd, ptr, size) == size ? 1 : 0;
179 
180  for (i = 0; i < nmemb; i++) {
181  if (write(stream->fd, ptr + size * i, size) != size)
182  return i;
183  }
184 
185  return nmemb;
186 }
187 
188 static inline int fgetc(FILE * stream) {
189  uint8_t v;
190 
191  if (!stream) {
192  set_errno(EINVAL);
193  return -1;
194  }
195 
196  if (read(stream->fd, &v, 1) != 1) {
197  stream->got_eof = 1;
198  return EOF;
199  }
200  return v;
201 }
202 
203 static inline int fseek(FILE * stream, off_t offset, int wheel) {
204  int r;
205  if (!stream) {
206  set_errno(EINVAL);
207  return -1;
208  }
209 
210  r = lseek(stream->fd, offset, wheel) != -1 ? 0 : -1;
211  if (!r)
212  stream->got_eof = 0;
213  return r;
214 }
215 
216 static inline char * fgets(char * s, int n, FILE * stream) {
217  int r, fd;
218  char c, * copy = s;
219  if (!stream) {
220  set_errno(EINVAL);
221  return NULL;
222  }
223 
224  fd = stream->fd;
225 
226  while (--n) {
227  r = read(fd, &c, 1);
228  switch (r) {
229  case 0:
230  stream->got_eof = 1;
231  *s = 0;
232  return copy;
233  case 1:
234  *s++ = c;
235  if (c == '\n') {
236  *s = 0;
237  return copy;
238  }
239  break;
240  case -1:
241  return NULL;
242  break;
243  }
244  };
245 
246  *s = 0;
247  return copy;
248 }
249 
250 static inline int getc() { return fgetc(stdin); }
251 static inline off_t ftell(FILE * stream) { return lseek(stream->fd, 0, SEEK_CUR); }
252 static inline int feof(FILE * stream) { return stream->got_eof; }
253 static inline int fileno(FILE * stream) { return stream->fd; }
254 static inline void rewind(FILE * stream) { fseek(stream, 0, SEEK_SET); }
255 
256 #endif