2 * AcessOS Basic C Library
\r
6 #include <acess/sys.h>
\r
11 #include "stdio_int.h"
\r
13 #define DEBUG_BUILD 0
\r
15 // === CONSTANTS ===
\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
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
32 * \fn FILE *freopen(char *file, char *mode, FILE *fp)
\r
34 EXPORT FILE *freopen(const char *file, const char *mode, FILE *fp)
\r
39 // Sanity Check Arguments
\r
40 if(!fp || !file || !mode) return NULL;
\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
58 for(i=1;mode[i];i++)
\r
62 case '+': fp->Flags |= FILE_FLAG_M_EXT;
\r
70 case 'r': openFlags = OPENFLAG_READ;
\r
71 if(fp->Flags & FILE_FLAG_M_EXT)
\r
72 openFlags |= OPENFLAG_WRITE;
\r
75 case 'w': openFlags = OPENFLAG_WRITE;
\r
76 if(fp->Flags & FILE_FLAG_M_EXT)
\r
77 openFlags |= OPENFLAG_READ;
\r
80 case 'x': openFlags = OPENFLAG_EXEC;
\r
86 fp->FD = reopen(fp->FD, file, openFlags);
\r
88 fp->FD = open(file, openFlags);
\r
94 if(mode[0] == 'a') {
\r
95 seek(fp->FD, 0, SEEK_END); //SEEK_END
\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
106 EXPORT FILE *fopen(const char *file, const char *mode)
\r
110 // Sanity Check Arguments
\r
111 if(!file || !mode) return NULL;
\r
113 // Create Return Structure
\r
114 retFile = get_file_struct();
\r
116 return freopen(file, mode, retFile);
\r
119 EXPORT void fclose(FILE *fp)
\r
125 EXPORT void fflush(FILE *fp)
\r
130 EXPORT long int ftell(FILE *fp)
\r
132 if(!fp || !fp->FD) return -1;
\r
134 return tell(fp->FD);
\r
137 EXPORT int fseek(FILE *fp, long int amt, int whence)
\r
139 if(!fp || !fp->FD) return -1;
\r
141 return seek(fp->FD, amt, whence);
\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
149 EXPORT int vfprintf(FILE *fp, const char *format, va_list args)
\r
151 va_list tmpList = args;
\r
155 if(!fp || !format) return -1;
\r
157 size = vsprintf(NULL, (char*)format, tmpList);
\r
159 buf = (char*)malloc(size+1);
\r
163 vsprintf(buf, (char*)format, args);
\r
166 write(fp->FD, size+1, buf);
\r
171 // Return written byte count
\r
176 * \fn int fprintf(FILE *fp, const char *format, ...)
\r
177 * \brief Print a formatted string to a stream
\r
179 EXPORT int fprintf(FILE *fp, const char *format, ...)
\r
185 va_start(args, format);
\r
186 ret = vfprintf(fp, (char*)format, args);
\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
196 EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)
\r
199 if(!fp || !fp->FD) return -1;
\r
201 ret = write(fp->FD, size*num, ptr);
\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
210 EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)
\r
213 if(!fp || !fp->FD) return -1;
\r
215 ret = read(fp->FD, size*num, ptr);
\r
221 * \fn EXPORT int fputc(int c, FILE *fp)
\r
222 * \brief Write a single character to the stream
\r
224 EXPORT int fputc(int c, FILE *fp)
\r
226 if(!fp || !fp->FD) return -1;
\r
227 return write(fp->FD, 1, &c);
\r
231 * \fn EXPORT int fgetc(FILE *fp)
\r
232 * \brief Read a character from the stream
\r
234 EXPORT int fgetc(FILE *fp)
\r
238 if(read(fp->FD, 1, &ret) == -1) return -1;
\r
242 // --- INTERNAL ---
\r
244 * \fn FILE *get_file_struct()
\r
245 * \brief Returns a file descriptor structure
\r
247 FILE *get_file_struct()
\r
250 for(i=0;i<STDIO_MAX_STREAMS;i++)
\r
252 if(_iob[i].Flags == 0) return &_iob[i];
\r
257 EXPORT int putchar(int ch)
\r
259 return write(_stdout, 1, (char*)&ch);
\r
262 EXPORT int puts(const char *str)
\r
269 len = write(_stdout, len, (char*)str);
\r
270 write(_stdout, 1, "\n");
\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
282 EXPORT int vsprintf(char *buf, const char *format, va_list args)
\r
294 while((c = *format++) != 0)
\r
296 // Non-control character
\r
298 if(buf) buf[pos] = c;
\r
303 // Control Character
\r
305 if(c == '%') { // Literal %
\r
306 if(buf) buf[pos] = '%';
\r
318 if('1' <= c && c <= '9')
\r
320 while('0' <= c && c <= '9')
\r
323 minSize += c - '0';
\r
328 // Check for long long
\r
344 case 'd': case 'i':
\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
351 // Unsigned Integer
\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
367 // Fall through to hex
\r
368 // Unsigned Hexadecimal
\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
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
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
391 arg = va_arg(args, uint32_t);
\r
392 p = (void*)(intptr_t)arg;
\r
394 if(!p) p = "(null)";
\r
407 // Unknown, just treat it as a character
\r
409 arg = va_arg(args, uint32_t);
\r
410 if(buf) buf[pos] = arg;
\r
415 if(buf) buf[pos] = '\0';
\r
420 const char cUCDIGITS[] = "0123456789ABCDEF";
\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
425 EXPORT void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned)
\r
436 if(bSigned && (int64_t)num < 0)
\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
449 tmpBuf[pos++] = cUCDIGITS[ num % base ]; // Last digit of {number}
\r
450 if(bSigned) tmpBuf[pos++] = '-'; // Append sign symbol if needed
\r
453 while(minLength-- > 0) buf[i++] = pad;
\r
454 while(pos-- > 0) buf[i++] = tmpBuf[pos]; // Reverse the order of characters
\r
459 * \fn EXPORT int printf(const char *format, ...)
\r
460 * \brief Print a string to stdout
\r
462 EXPORT int printf(const char *format, ...)
\r
470 va_start(args, format);
\r
471 size = vsprintf(NULL, (char*)format, args);
\r
475 buf = (char*)malloc(size+1);
\r
479 va_start(args, format);
\r
480 vsprintf(buf, (char*)format, args);
\r
484 write(_stdout, size+1, buf);
\r
495 va_start(args, format);
\r
496 ret = fprintfv(stdout, (char*)format, args);
\r
503 * \fn EXPORT int sprintf(const char *buf, char *format, ...)
\r
504 * \brief Print a formatted string to a buffer
\r
506 EXPORT int sprintf(char *buf, const char *format, ...)
\r
510 va_start(args, format);
\r
511 ret = vsprintf((char*)buf, (char*)format, args);
\r