2 * AcessOS Basic C Library
\r
6 #include <acess/sys.h>
\r
11 #include "stdio_int.h"
\r
13 #define WRITE_STR(_fd, _str) write(_fd, _str, sizeof(_str))
\r
15 #define DEBUG_BUILD 0
\r
17 // === CONSTANTS ===
\r
21 // === PROTOTYPES ===
\r
22 EXPORT void itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned);
\r
23 struct sFILE *get_file_struct();
\r
26 struct sFILE _iob[STDIO_MAX_STREAMS]; // IO Buffer
\r
27 struct sFILE *stdin; // Standard Input
\r
28 struct sFILE *stdout; // Standard Output
\r
29 struct sFILE *stderr; // Standard Error
\r
30 ///\note Initialised in SoMain
\r
34 * \fn FILE *freopen(char *file, char *mode, FILE *fp)
\r
36 EXPORT FILE *freopen(const char *file, const char *mode, FILE *fp)
\r
41 // Sanity Check Arguments
\r
42 if(!fp || !file || !mode) return NULL;
\r
52 case 'r': fp->Flags = FILE_FLAG_MODE_READ; break;
\r
53 case 'w': fp->Flags = FILE_FLAG_MODE_WRITE; break;
\r
54 case 'a': fp->Flags = FILE_FLAG_MODE_APPEND; break;
\r
55 case 'x': fp->Flags = FILE_FLAG_MODE_EXEC; break;
\r
60 for(i=1;mode[i];i++)
\r
64 case '+': fp->Flags |= FILE_FLAG_M_EXT;
\r
72 case 'r': openFlags = OPENFLAG_READ;
\r
73 if(fp->Flags & FILE_FLAG_M_EXT)
\r
74 openFlags |= OPENFLAG_WRITE;
\r
77 case 'w': openFlags = OPENFLAG_WRITE;
\r
78 if(fp->Flags & FILE_FLAG_M_EXT)
\r
79 openFlags |= OPENFLAG_READ;
\r
82 case 'x': openFlags = OPENFLAG_EXEC;
\r
88 fp->FD = reopen(fp->FD, file, openFlags);
\r
90 fp->FD = open(file, openFlags);
\r
96 if(mode[0] == 'a') {
\r
97 seek(fp->FD, 0, SEEK_END); //SEEK_END
\r
103 \fn FILE *fopen(const char *file, const char *mode)
\r
104 \brief Opens a file and returns the pointer
\r
105 \param file String - Filename to open
\r
106 \param mode Mode to open in
\r
108 EXPORT FILE *fopen(const char *file, const char *mode)
\r
112 // Sanity Check Arguments
\r
113 if(!file || !mode) return NULL;
\r
115 // Create Return Structure
\r
116 retFile = get_file_struct();
\r
118 return freopen(file, mode, retFile);
\r
121 EXPORT int fclose(FILE *fp)
\r
129 EXPORT void fflush(FILE *fp)
\r
134 EXPORT off_t ftell(FILE *fp)
\r
136 if(!fp || !fp->FD) return -1;
\r
138 return tell(fp->FD);
\r
141 EXPORT int fseek(FILE *fp, long int amt, int whence)
\r
143 if(!fp || !fp->FD) return -1;
\r
145 return seek(fp->FD, amt, whence);
\r
150 * \fn EXPORT int vfprintf(FILE *fp, const char *format, va_list args)
\r
151 * \brief Print to a file from a variable argument list
\r
153 EXPORT int vfprintf(FILE *fp, const char *format, va_list args)
\r
160 if(!fp || !format) return -1;
\r
162 va_copy(tmpList, args);
\r
164 size = vsnprintf(sbuf, sizeof(sbuf), (char*)format, tmpList);
\r
166 if( size >= sizeof(sbuf) )
\r
168 buf = (char*)malloc(size+1);
\r
170 WRITE_STR(_stdout, "vfprintf ERROR: malloc() failed");
\r
176 vsnprintf(buf, size+1, (char*)format, args);
\r
180 write(fp->FD, buf, size);
\r
185 // Return written byte count
\r
190 * \fn int fprintf(FILE *fp, const char *format, ...)
\r
191 * \brief Print a formatted string to a stream
\r
193 EXPORT int fprintf(FILE *fp, const char *format, ...)
\r
199 va_start(args, format);
\r
200 ret = vfprintf(fp, (char*)format, args);
\r
207 * \fn EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)
\r
208 * \brief Write to a stream
\r
210 EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)
\r
213 if(!fp || !fp->FD) return -1;
\r
215 ret = write(fp->FD, ptr, size*num);
\r
221 * \fn EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)
\r
222 * \brief Read from a stream
\r
224 EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)
\r
227 if(!fp || !fp->FD) return -1;
\r
229 ret = read(fp->FD, ptr, size*num);
\r
235 * \fn EXPORT int fputc(int c, FILE *fp)
\r
236 * \brief Write a single character to the stream
\r
238 EXPORT int fputc(int c, FILE *fp)
\r
240 if(!fp || !fp->FD) return -1;
\r
241 return write(fp->FD, &c, 1);
\r
244 EXPORT int putchar(int c)
\r
247 return write(_stdout, &c, 1);
\r
251 * \fn EXPORT int fgetc(FILE *fp)
\r
252 * \brief Read a character from the stream
\r
254 EXPORT int fgetc(FILE *fp)
\r
258 if(read(fp->FD, &ret, 1) == -1) return -1;
\r
262 EXPORT int getchar(void)
\r
265 if(read(_stdin, &ret, 1) != 1) return -1;
\r
269 // --- INTERNAL ---
\r
271 * \fn FILE *get_file_struct()
\r
272 * \brief Returns a file descriptor structure
\r
274 FILE *get_file_struct()
\r
277 for(i=0;i<STDIO_MAX_STREAMS;i++)
\r
279 if(_iob[i].Flags == 0) return &_iob[i];
\r
284 EXPORT int puts(const char *str)
\r
291 len = write(_stdout, str, len);
\r
292 write(_stdout, "\n", 1);
\r
296 EXPORT int vsprintf(char * __s, const char *__format, va_list __args)
\r
298 return vsnprintf(__s, 0x7FFFFFFF, __format, __args);
\r
303 * \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args)
\r
304 * \brief Prints a formatted string to a buffer
\r
305 * \param buf Pointer - Destination Buffer
\r
306 * \param format String - Format String
\r
307 * \param args VarArgs List - Arguments
\r
309 EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list args)
\r
312 int c, minSize, precision, len;
\r
317 int bLongLong, bPadLeft;
\r
319 void _addchar(char ch)
\r
321 if(buf && pos < __maxlen) buf[pos] = ch;
\r
327 while((c = *format++) != 0)
\r
329 // Non-control character
\r
335 // Control Character
\r
337 if(c == '%') { // Literal %
\r
348 // Padding Character
\r
356 minSize = va_arg(args, size_t);
\r
360 if('1' <= c && c <= '9')
\r
363 while('0' <= c && c <= '9')
\r
366 minSize += c - '0';
\r
376 precision = va_arg(args, size_t);
\r
379 else if('1' <= c && c <= '9')
\r
382 while('0' <= c && c <= '9')
\r
385 precision += c - '0';
\r
391 // Check for long long
\r
401 // Just help things along later
\r
408 case 'd': case 'i':
\r
410 if(bLongLong) arg = va_arg(args, int64_t);
\r
411 else arg = va_arg(args, int32_t);
\r
412 itoa(tmp, arg, 10, minSize, pad, 1);
\r
416 // Unsigned Integer
\r
419 if(bLongLong) arg = va_arg(args, uint64_t);
\r
420 else arg = va_arg(args, uint32_t);
\r
421 itoa(tmp, arg, 10, minSize, pad, 0);
\r
430 arg = va_arg(args, intptr_t);
\r
431 itoa(tmp, arg, 16, minSize, pad, 0);
\r
434 // Unsigned Hexadecimal
\r
436 if(bLongLong) arg = va_arg(args, uint64_t);
\r
437 else arg = va_arg(args, uint32_t);
\r
438 itoa(tmp, arg, 16, minSize, pad, 0);
\r
444 if(bLongLong) arg = va_arg(args, uint64_t);
\r
445 else arg = va_arg(args, uint32_t);
\r
446 itoa(tmp, arg, 8, minSize, pad, 0);
\r
452 if(bLongLong) arg = va_arg(args, uint64_t);
\r
453 else arg = va_arg(args, uint32_t);
\r
454 itoa(tmp, arg, 2, minSize, pad, 0);
\r
460 p = va_arg(args, char*);
\r
462 if(!p) p = "(null)";
\r
463 //_SysDebug("vsnprintf: p = '%s'", p);
\r
465 len = strnlen(p, precision);
\r
468 if(bPadLeft) while(minSize > len++) _addchar(pad);
\r
470 if(precision >= 0 && precision -- == 0)
\r
474 if(!bPadLeft) while(minSize > len++) _addchar(pad);
\r
477 // Unknown, just treat it as a character
\r
479 arg = va_arg(args, uint32_t);
\r
487 //_SysDebug("vsnprintf: buf = '%s'", buf);
\r
492 const char cUCDIGITS[] = "0123456789ABCDEF";
\r
494 * \fn static void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned)
\r
495 * \brief Convert an integer into a character string
\r
496 * \param buf Destination Buffer
\r
497 * \param num Number to convert
\r
498 * \param base Base-n number output
\r
499 * \param minLength Minimum length of output
\r
500 * \param pad Padding used to ensure minLength
\r
501 * \param bSigned Signed number output?
\r
503 EXPORT void itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned)
\r
509 if(base > 16 || base < 2) {
\r
514 if(bSigned && (int64_t)num < 0)
\r
521 // Encode into reversed string
\r
522 while(num > base-1) {
\r
523 tmpBuf[pos++] = cUCDIGITS[ num % base ];
\r
524 num = (uint64_t) num / (uint64_t)base; // Shift {number} right 1 digit
\r
527 tmpBuf[pos++] = cUCDIGITS[ num % base ]; // Last digit of {number}
\r
528 if(bSigned) tmpBuf[pos++] = '-'; // Append sign symbol if needed
\r
532 while(minLength-- > 0) buf[i++] = pad;
\r
533 while(pos-- > 0) buf[i++] = tmpBuf[pos]; // Reverse the order of characters
\r
538 * \fn EXPORT int printf(const char *format, ...)
\r
539 * \brief Print a string to stdout
\r
541 EXPORT int printf(const char *format, ...)
\r
550 va_start(args, format);
\r
551 size = vsnprintf(sbuf, 1024, (char*)format, args);
\r
554 if( size >= 1024 ) {
\r
556 buf = (char*)malloc(size+1);
\r
558 WRITE_STR(_stdout, "PRINTF ERROR: malloc() failed\n");
\r
564 va_start(args, format);
\r
565 vsnprintf(buf, size+1, (char*)format, args);
\r
570 write(_stdout, buf, size+1);
\r
581 va_start(args, format);
\r
582 ret = fprintfv(stdout, (char*)format, args);
\r
589 * \fn EXPORT int sprintf(const char *buf, char *format, ...)
\r
590 * \brief Print a formatted string to a buffer
\r
592 EXPORT int sprintf(char *buf, const char *format, ...)
\r
596 va_start(args, format);
\r
597 ret = vsprintf((char*)buf, (char*)format, args);
\r
603 * \fn EXPORT int snprintf(const char *buf, size_t maxlen, char *format, ...)
\r
604 * \brief Print a formatted string to a buffer
\r
606 EXPORT int snprintf(char *buf, size_t maxlen, const char *format, ...)
\r
610 va_start(args, format);
\r
611 ret = vsnprintf((char*)buf, maxlen, (char*)format, args);
\r