5fdac4cc220950f56f8ea34e592ea0461bd9288c
[tpg/acess2.git] / Usermode / Libraries / libc.so_src / fileIO.c
1 /*\r
2  * AcessOS Basic C Library\r
3  * stdio.c\r
4  */\r
5 #include "config.h"\r
6 #include <acess/sys.h>\r
7 #include <stdlib.h>\r
8 #include <stdio.h>\r
9 #include <string.h>\r
10 #include "lib.h"\r
11 #include "stdio_int.h"\r
12 \r
13 #define DEBUG_BUILD     0\r
14 \r
15 // === CONSTANTS ===\r
16 #define _stdin  0\r
17 #define _stdout 1\r
18 \r
19 // === PROTOTYPES ===\r
20 EXPORT void     itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned);\r
21 struct sFILE    *get_file_struct();\r
22 \r
23 // === GLOBALS ===\r
24 struct sFILE    _iob[STDIO_MAX_STREAMS];        // IO Buffer\r
25 struct sFILE    *stdin; // Standard Input\r
26 struct sFILE    *stdout;        // Standard Output\r
27 struct sFILE    *stderr;        // Standard Error\r
28 ///\note Initialised in SoMain\r
29 \r
30 // === CODE ===\r
31 /**\r
32  * \fn FILE *freopen(char *file, char *mode, FILE *fp)\r
33  */\r
34 EXPORT FILE *freopen(const char *file, const char *mode, FILE *fp)\r
35 {\r
36          int    openFlags = 0;\r
37          int    i;\r
38         \r
39         // Sanity Check Arguments\r
40         if(!fp || !file || !mode)       return NULL;\r
41         \r
42         if(fp->Flags) {\r
43                 fflush(fp);\r
44         } else\r
45                 fp->FD = -1;\r
46         \r
47         // Get main mode\r
48         switch(mode[0])\r
49         {\r
50         case 'r':       fp->Flags = FILE_FLAG_MODE_READ;        break;\r
51         case 'w':       fp->Flags = FILE_FLAG_MODE_WRITE;       break;\r
52         case 'a':       fp->Flags = FILE_FLAG_MODE_APPEND;      break;\r
53         case 'x':       fp->Flags = FILE_FLAG_MODE_EXEC;        break;\r
54         default:\r
55                 return NULL;\r
56         }\r
57         // Get Modifiers\r
58         for(i=1;mode[i];i++)\r
59         {\r
60                 switch(mode[i])\r
61                 {\r
62                 case '+':       fp->Flags |= FILE_FLAG_M_EXT;\r
63                 }\r
64         }\r
65         \r
66         // Get Open Flags\r
67         switch(mode[0])\r
68         {\r
69         // Read\r
70         case 'r':       openFlags = OPENFLAG_READ;\r
71                 if(fp->Flags & FILE_FLAG_M_EXT)\r
72                         openFlags |= OPENFLAG_WRITE;\r
73                 break;\r
74         // Write\r
75         case 'w':       openFlags = OPENFLAG_WRITE;\r
76                 if(fp->Flags & FILE_FLAG_M_EXT)\r
77                         openFlags |= OPENFLAG_READ;\r
78                 break;\r
79         // Execute\r
80         case 'x':       openFlags = OPENFLAG_EXEC;\r
81                 break;\r
82         }\r
83         \r
84         //Open File\r
85         if(fp->FD != -1)\r
86                 fp->FD = reopen(fp->FD, file, openFlags);\r
87         else\r
88                 fp->FD = open(file, openFlags);\r
89         if(fp->FD == -1) {\r
90                 fp->Flags = 0;\r
91                 return NULL;\r
92         }\r
93         \r
94         if(mode[0] == 'a') {\r
95                 seek(fp->FD, 0, SEEK_END);      //SEEK_END\r
96         }\r
97         \r
98         return fp;\r
99 }\r
100 /**\r
101  \fn FILE *fopen(const char *file, const char *mode)\r
102  \brief Opens a file and returns the pointer\r
103  \param file    String - Filename to open\r
104  \param mode    Mode to open in\r
105 */\r
106 EXPORT FILE *fopen(const char *file, const char *mode)\r
107 {\r
108         FILE    *retFile;\r
109         \r
110         // Sanity Check Arguments\r
111         if(!file || !mode)      return NULL;\r
112         \r
113         // Create Return Structure\r
114         retFile = get_file_struct();\r
115         \r
116         return freopen(file, mode, retFile);\r
117 }\r
118 \r
119 EXPORT void fclose(FILE *fp)\r
120 {\r
121         close(fp->FD);\r
122         free(fp);\r
123 }\r
124 \r
125 EXPORT void fflush(FILE *fp)\r
126 {\r
127         ///\todo Implement\r
128 }\r
129 \r
130 EXPORT long int ftell(FILE *fp)\r
131 {\r
132         if(!fp || !fp->FD)      return -1;\r
133         \r
134         return tell(fp->FD);\r
135 }\r
136 \r
137 EXPORT int fseek(FILE *fp, long int amt, int whence)\r
138 {\r
139         if(!fp || !fp->FD)      return -1;\r
140         \r
141         return seek(fp->FD, amt, whence);\r
142 }\r
143 \r
144 \r
145 /**\r
146  * \fn EXPORT int vfprintf(FILE *fp, const char *format, va_list args)\r
147  * \brief Print to a file from a variable argument list\r
148  */\r
149 EXPORT int vfprintf(FILE *fp, const char *format, va_list args)\r
150 {\r
151         va_list tmpList = args;\r
152          int    size;\r
153         char    *buf;\r
154          \r
155         if(!fp || !format)      return -1;\r
156         \r
157         size = vsprintf(NULL, (char*)format, tmpList);\r
158         \r
159         buf = (char*)malloc(size+1);\r
160         buf[size] = '\0';\r
161         \r
162         // Print\r
163         vsprintf(buf, (char*)format, args);\r
164         \r
165         // Write to stream\r
166         write(fp->FD, size+1, buf);\r
167         \r
168         // Free buffer\r
169         free(buf);\r
170         \r
171         // Return written byte count\r
172         return size;\r
173 }\r
174 \r
175 /**\r
176  * \fn int fprintf(FILE *fp, const char *format, ...)\r
177  * \brief Print a formatted string to a stream\r
178  */\r
179 EXPORT int fprintf(FILE *fp, const char *format, ...)\r
180 {\r
181         va_list args;\r
182          int    ret;\r
183         \r
184         // Get Size\r
185         va_start(args, format);\r
186         ret = vfprintf(fp, (char*)format, args);\r
187         va_end(args);\r
188         \r
189         return ret;\r
190 }\r
191 \r
192 /**\r
193  * \fn EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)\r
194  * \brief Write to a stream\r
195  */\r
196 EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)\r
197 {\r
198          int    ret;\r
199         if(!fp || !fp->FD)      return -1;\r
200         \r
201         ret = write(fp->FD, size*num, ptr);\r
202         \r
203         return ret;\r
204 }\r
205 \r
206 /**\r
207  * \fn EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)\r
208  * \brief Read from a stream\r
209  */\r
210 EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)\r
211 {\r
212          int    ret;\r
213         if(!fp || !fp->FD)      return -1;\r
214         \r
215         ret = read(fp->FD, size*num, ptr);\r
216         \r
217         return ret;\r
218 }\r
219 \r
220 /**\r
221  * \fn EXPORT int fputc(int c, FILE *fp)\r
222  * \brief Write a single character to the stream\r
223  */\r
224 EXPORT int fputc(int c, FILE *fp)\r
225 {\r
226         if(!fp || !fp->FD)      return -1;\r
227         return write(fp->FD, 1, &c);\r
228 }\r
229 \r
230 /**\r
231  * \fn EXPORT int fgetc(FILE *fp)\r
232  * \brief Read a character from the stream\r
233  */\r
234 EXPORT int fgetc(FILE *fp)\r
235 {\r
236          int    ret = 0;\r
237         if(!fp) return -1;\r
238         if(read(fp->FD, 1, &ret) == -1) return -1;\r
239         return ret;\r
240 }\r
241 \r
242 // --- INTERNAL ---\r
243 /**\r
244  * \fn FILE *get_file_struct()\r
245  * \brief Returns a file descriptor structure\r
246  */\r
247 FILE *get_file_struct()\r
248 {\r
249          int    i;\r
250         for(i=0;i<STDIO_MAX_STREAMS;i++)\r
251         {\r
252                 if(_iob[i].Flags == 0)  return &_iob[i];\r
253         }\r
254         return NULL;\r
255 }\r
256 \r
257 EXPORT int putchar(int ch)\r
258 {\r
259         return write(_stdout, 1, (char*)&ch);\r
260 }\r
261 \r
262 EXPORT int      puts(const char *str)\r
263 {\r
264          int    len;\r
265         \r
266         if(!str)        return 0;\r
267         len = strlen(str);\r
268         \r
269         len = write(_stdout, len, (char*)str);\r
270         write(_stdout, 1, "\n");\r
271         return len;\r
272 }\r
273 \r
274 //sprintfv\r
275 /**\r
276  \fn EXPORT void vsprintf(char *buf, const char *format, va_list args)\r
277  \brief Prints a formatted string to a buffer\r
278  \param buf     Pointer - Destination Buffer\r
279  \param format  String - Format String\r
280  \param args    VarArgs List - Arguments\r
281 */\r
282 EXPORT int vsprintf(char *buf, const char *format, va_list args)\r
283 {\r
284         char    tmp[33];\r
285          int    c, minSize;\r
286          int    pos = 0;\r
287         char    *p;\r
288         char    pad;\r
289         uint64_t        arg;\r
290          int    bLongLong;\r
291 \r
292         tmp[32] = '\0';\r
293         \r
294         while((c = *format++) != 0)\r
295         {\r
296                 // Non-control character\r
297                 if (c != '%') {\r
298                         if(buf) buf[pos] = c;\r
299                         pos ++;\r
300                         continue;\r
301                 }\r
302                 \r
303                 // Control Character\r
304                 c = *format++;\r
305                 if(c == '%') {  // Literal %\r
306                         if(buf) buf[pos] = '%';\r
307                         pos ++;\r
308                         continue;\r
309                 }\r
310                 \r
311                 // Padding\r
312                 if(c == '0') {\r
313                         pad = '0';\r
314                         c = *format++;\r
315                 } else\r
316                         pad = ' ';\r
317                 minSize = 0;\r
318                 if('1' <= c && c <= '9')\r
319                 {\r
320                         while('0' <= c && c <= '9')\r
321                         {\r
322                                 minSize *= 10;\r
323                                 minSize += c - '0';\r
324                                 c = *format++;\r
325                         }\r
326                 }\r
327         \r
328                 // Check for long long\r
329                 bLongLong = 0;\r
330                 if(c == 'l')\r
331                 {\r
332                         c = *format++;\r
333                         if(c == 'l') {\r
334                                 bLongLong = 1;\r
335                         }\r
336                 }\r
337                         \r
338                 p = tmp;\r
339                 \r
340                 // Get Type\r
341                 switch( c )\r
342                 {\r
343                 // Signed Integer\r
344                 case 'd':       case 'i':\r
345                         // Get Argument\r
346                         if(bLongLong)   arg = va_arg(args, int64_t);\r
347                         else                    arg = va_arg(args, int32_t);\r
348                         itoa(tmp, arg, 10, minSize, pad, 1);\r
349                         goto sprintf_puts;\r
350                 \r
351                 // Unsigned Integer\r
352                 case 'u':\r
353                         // Get Argument\r
354                         if(bLongLong)   arg = va_arg(args, uint64_t);\r
355                         else                    arg = va_arg(args, uint32_t);\r
356                         itoa(tmp, arg, 10, minSize, pad, 0);\r
357                         goto sprintf_puts;\r
358                 \r
359                 // Pointer\r
360                 case 'p':\r
361                         if(buf) {\r
362                                 buf[pos] = '*';\r
363                                 buf[pos+1] = '0';\r
364                                 buf[pos+2] = 'x';\r
365                         }\r
366                         pos += 3;\r
367                         // Fall through to hex\r
368                 // Unsigned Hexadecimal\r
369                 case 'x':\r
370                         if(bLongLong)   arg = va_arg(args, uint64_t);\r
371                         else                    arg = va_arg(args, uint32_t);\r
372                         itoa(tmp, arg, 16, minSize, pad, 0);\r
373                         goto sprintf_puts;\r
374                 \r
375                 // Unsigned Octal\r
376                 case 'o':\r
377                         if(bLongLong)   arg = va_arg(args, uint64_t);\r
378                         else                    arg = va_arg(args, uint32_t);\r
379                         itoa(tmp, arg, 8, minSize, pad, 0);\r
380                         goto sprintf_puts;\r
381                 \r
382                 // Unsigned binary\r
383                 case 'b':\r
384                         if(bLongLong)   arg = va_arg(args, uint64_t);\r
385                         else                    arg = va_arg(args, uint32_t);\r
386                         itoa(tmp, arg, 2, minSize, pad, 0);\r
387                         goto sprintf_puts;\r
388 \r
389                 // String\r
390                 case 's':\r
391                         arg = va_arg(args, uint32_t);\r
392                         p = (void*)(intptr_t)arg;\r
393                 sprintf_puts:\r
394                         if(!p)  p = "(null)";\r
395                         if(buf) {\r
396                                 while(*p) {\r
397                                         buf[pos++] = *p++;\r
398                                 }\r
399                         }\r
400                         else {\r
401                                 while(*p) {\r
402                                         pos++; p++;\r
403                                 }\r
404                         }\r
405                         break;\r
406 \r
407                 // Unknown, just treat it as a character\r
408                 default:\r
409                         arg = va_arg(args, uint32_t);\r
410                         if(buf) buf[pos] = arg;\r
411                         pos ++;\r
412                         break;\r
413                 }\r
414     }\r
415         if(buf) buf[pos] = '\0';\r
416         \r
417         return pos;\r
418 }\r
419 \r
420 const char cUCDIGITS[] = "0123456789ABCDEF";\r
421 /**\r
422  * \fn static void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned)\r
423  * \brief Convert an integer into a character string\r
424  */\r
425 EXPORT void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned)\r
426 {\r
427         char    tmpBuf[32];\r
428          int    pos=0, i;\r
429 \r
430         if(!buf)        return;\r
431         if(base > 16) {\r
432                 buf[0] = 0;\r
433                 return;\r
434         }\r
435         \r
436         if(bSigned && (int64_t)num < 0)\r
437         {\r
438                 num = -num;\r
439                 bSigned = 1;\r
440         } else\r
441                 bSigned = 0;\r
442         \r
443         while(num > base-1) {\r
444                 tmpBuf[pos] = cUCDIGITS[ num % base ];\r
445                 num = (long) num / base;                // Shift {number} right 1 digit\r
446                 pos++;\r
447         }\r
448 \r
449         tmpBuf[pos++] = cUCDIGITS[ num % base ];                // Last digit of {number}\r
450         if(bSigned)     tmpBuf[pos++] = '-';    // Append sign symbol if needed\r
451         i = 0;\r
452         minLength -= pos;\r
453         while(minLength-- > 0)  buf[i++] = pad;\r
454         while(pos-- > 0)                buf[i++] = tmpBuf[pos]; // Reverse the order of characters\r
455         buf[i] = 0;\r
456 }\r
457 \r
458 /**\r
459  * \fn EXPORT int printf(const char *format, ...)\r
460  * \brief Print a string to stdout\r
461  */\r
462 EXPORT int printf(const char *format, ...)\r
463 {\r
464         #if 1\r
465          int    size;\r
466         char    *buf;\r
467         va_list args;\r
468         \r
469         // Get final size\r
470         va_start(args, format);\r
471         size = vsprintf(NULL, (char*)format, args);\r
472         va_end(args);\r
473         \r
474         // Allocate buffer\r
475         buf = (char*)malloc(size+1);\r
476         buf[size] = '\0';\r
477         \r
478         // Fill Buffer\r
479         va_start(args, format);\r
480         vsprintf(buf, (char*)format, args);\r
481         va_end(args);\r
482         \r
483         // Send to stdout\r
484         write(_stdout, size+1, buf);\r
485         \r
486         // Free buffer\r
487         free(buf);\r
488         // Return\r
489         return size;\r
490         \r
491         #else\r
492         \r
493          int    ret;\r
494         va_list args;\r
495         va_start(args, format);\r
496         ret = fprintfv(stdout, (char*)format, args);\r
497         va_end(args);\r
498         return ret;\r
499         #endif\r
500 }\r
501 \r
502 /**\r
503  * \fn EXPORT int sprintf(const char *buf, char *format, ...)\r
504  * \brief Print a formatted string to a buffer\r
505  */\r
506 EXPORT int sprintf(char *buf, const char *format, ...)\r
507 {\r
508          int    ret;\r
509         va_list args;\r
510         va_start(args, format);\r
511         ret = vsprintf((char*)buf, (char*)format, args);\r
512         va_end(args);\r
513         return ret;\r
514 }\r

UCC git Repository :: git.ucc.asn.au