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

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