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
33 int _fopen_modetoflags(const char *mode)
\r
40 case 'r': flags = FILE_FLAG_MODE_READ; break;
\r
41 case 'w': flags = FILE_FLAG_MODE_WRITE; break;
\r
42 case 'a': flags = FILE_FLAG_MODE_APPEND; break;
\r
43 case 'x': flags = FILE_FLAG_MODE_EXEC; break; // Acess addon
\r
50 for( ; *mode; mode ++ )
\r
54 case 'b': flags |= FILE_FLAG_M_BINARY; break;
\r
55 case '+': flags |= FILE_FLAG_M_EXT; break;
\r
65 * \fn FILE *freopen(char *file, char *mode, FILE *fp)
\r
67 EXPORT FILE *freopen(const char *file, const char *mode, FILE *fp)
\r
71 // Sanity Check Arguments
\r
72 if(!fp || !file || !mode) return NULL;
\r
79 fp->Flags = _fopen_modetoflags(mode);
\r
84 switch(fp->Flags & FILE_FLAG_MODE_MASK)
\r
87 case FILE_FLAG_MODE_READ:
\r
88 openFlags = OPENFLAG_READ;
\r
89 if(fp->Flags & FILE_FLAG_M_EXT)
\r
90 openFlags |= OPENFLAG_WRITE;
\r
93 case FILE_FLAG_MODE_WRITE:
\r
94 openFlags = OPENFLAG_WRITE;
\r
95 if(fp->Flags & FILE_FLAG_M_EXT)
\r
96 openFlags |= OPENFLAG_READ;
\r
99 case FILE_FLAG_MODE_APPEND:
\r
100 openFlags = OPENFLAG_APPEND;
\r
101 if(fp->Flags & FILE_FLAG_M_EXT)
\r
102 openFlags |= OPENFLAG_READ;
\r
105 case FILE_FLAG_MODE_EXEC:
\r
106 openFlags = OPENFLAG_EXEC;
\r
112 fp->FD = _SysReopen(fp->FD, file, openFlags);
\r
114 fp->FD = _SysOpen(file, openFlags);
\r
120 if( (fp->Flags & FILE_FLAG_MODE_MASK) == FILE_FLAG_MODE_APPEND ) {
\r
121 _SysSeek(fp->FD, 0, SEEK_END); //SEEK_END
\r
127 \fn FILE *fopen(const char *file, const char *mode)
\r
128 \brief Opens a file and returns the pointer
\r
129 \param file String - Filename to open
\r
130 \param mode Mode to open in
\r
132 EXPORT FILE *fopen(const char *file, const char *mode)
\r
136 // Sanity Check Arguments
\r
137 if(!file || !mode) return NULL;
\r
139 // Create Return Structure
\r
140 retFile = get_file_struct();
\r
142 return freopen(file, mode, retFile);
\r
145 EXPORT FILE *fmemopen(void *buffer, size_t length, const char *mode)
\r
149 if( !buffer || !mode ) return NULL;
\r
151 ret = get_file_struct();
\r
154 ret->Flags = _fopen_modetoflags(mode);
\r
155 if(ret->Flags == -1) {
\r
160 ret->Buffer = buffer;
\r
161 ret->BufferStart = 0;
\r
162 ret->BufferSize = length;
\r
167 EXPORT int fclose(FILE *fp)
\r
170 if( fp->FD != -1 ) {
\r
178 EXPORT void fflush(FILE *fp)
\r
180 if( !fp || fp->FD == -1 )
\r
183 if( !(fp->Flags & FILE_FLAG_DIRTY) )
\r
186 // Nothing to do for memory files
\r
191 EXPORT void clearerr(FILE *fp)
\r
193 if( !fp || fp->FD == -1 )
\r
196 // TODO: Impliment clearerr()
\r
199 EXPORT int feof(FILE *fp)
\r
201 if( !fp || fp->FD == -1 )
\r
203 return !!(fp->Flags & FILE_FLAG_EOF);
\r
206 EXPORT int ferror(FILE *fp)
\r
208 if( !fp || fp->FD == -1 )
\r
212 EXPORT int fileno(FILE *stream)
\r
217 EXPORT off_t ftell(FILE *fp)
\r
219 if(!fp || fp->FD == -1) return -1;
\r
224 return _SysTell(fp->FD);
\r
227 EXPORT int fseek(FILE *fp, long int amt, int whence)
\r
229 if(!fp || fp->FD == -1) return -1;
\r
231 if( fp->FD == -2 ) {
\r
241 if( fp->BufferSize < (size_t)amt )
\r
244 fp->Pos = fp->BufferSize - amt;
\r
247 if(fp->Pos > (off_t)fp->BufferSize) {
\r
248 fp->Pos = fp->BufferSize;
\r
249 fp->Flags |= FILE_FLAG_EOF;
\r
254 return _SysSeek(fp->FD, amt, whence);
\r
259 * \fn EXPORT int vfprintf(FILE *fp, const char *format, va_list args)
\r
260 * \brief Print to a file from a variable argument list
\r
262 EXPORT int vfprintf(FILE *fp, const char *format, va_list args)
\r
267 if(!fp || !format) return -1;
\r
269 va_copy(tmpList, args);
\r
271 size = vsnprintf(NULL, 0, (char*)format, tmpList);
\r
273 vsnprintf(buf, size+1, (char*)format, args);
\r
276 fwrite(buf, size, 1, fp);
\r
278 // Return written byte count
\r
283 * \fn int fprintf(FILE *fp, const char *format, ...)
\r
284 * \brief Print a formatted string to a stream
\r
286 EXPORT int fprintf(FILE *fp, const char *format, ...)
\r
292 va_start(args, format);
\r
293 ret = vfprintf(fp, (char*)format, args);
\r
300 * \fn EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)
\r
301 * \brief Write to a stream
\r
303 EXPORT size_t fwrite(const void *ptr, size_t size, size_t num, FILE *fp)
\r
307 if(!fp || fp->FD == -1)
\r
310 if( fp->FD == -2 ) {
\r
311 size_t avail = (fp->BufferSize - fp->Pos) / size;
\r
313 fp->Flags |= FILE_FLAG_EOF;
\r
314 if( num > avail ) num = avail;
\r
315 size_t bytes = num * size;
\r
316 memcpy((char*)fp->Buffer + fp->Pos, ptr, bytes);
\r
321 ret = _SysWrite(fp->FD, ptr, size*num);
\r
329 * \fn EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)
\r
330 * \brief Read from a stream
\r
332 EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)
\r
336 if(!fp || fp->FD == -1)
\r
339 if( fp->FD == -2 ) {
\r
340 size_t avail = (fp->BufferSize - fp->Pos) / size;
\r
342 fp->Flags |= FILE_FLAG_EOF;
\r
343 if( num > avail ) num = avail;
\r
344 size_t bytes = num * size;
\r
345 memcpy(ptr, (char*)fp->Buffer + fp->Pos, bytes);
\r
350 ret = _SysRead(fp->FD, ptr, size*num);
\r
351 if( ret == (size_t)-1)
\r
353 if( ret == 0 && size*num > 0 ) {
\r
354 fp->Flags |= FILE_FLAG_EOF;
\r
364 * \brief Write a string to a stream (without trailing \n)
\r
366 EXPORT int fputs(const char *s, FILE *fp)
\r
368 int len = strlen(s);
\r
369 return fwrite(s, 1, len, fp);
\r
373 * \brief Read a line (and possible trailing \n into a buffer)
\r
375 EXPORT char *fgets(char *s, int size, FILE *fp)
\r
379 while( ofs < size && ch != '\n' )
\r
381 if( fread(&ch, 1, 1, fp) != 1 )
\r
391 * \fn EXPORT int fputc(int c, FILE *fp)
\r
392 * \brief Write a single character to the stream
\r
394 EXPORT int fputc(int c, FILE *fp)
\r
396 return fwrite(&c, 1, 1, fp);
\r
399 EXPORT int putchar(int c)
\r
402 return _SysWrite(_stdout, &c, 1);
\r
406 * \fn EXPORT int fgetc(FILE *fp)
\r
407 * \brief Read a character from the stream
\r
409 EXPORT int fgetc(FILE *fp)
\r
412 if( fread(&ret, 1, 1, fp) != 1 )
\r
417 EXPORT int getchar(void)
\r
420 if(_SysRead(_stdin, &ret, 1) != 1) return -1;
\r
424 // --- INTERNAL ---
\r
426 * \fn FILE *get_file_struct()
\r
427 * \brief Returns a file descriptor structure
\r
429 FILE *get_file_struct()
\r
432 for(i=0;i<STDIO_MAX_STREAMS;i++)
\r
434 if(_iob[i].Flags & FILE_FLAG_ALLOC)
\r
436 _iob[i].Flags |= FILE_FLAG_ALLOC;
\r
444 EXPORT int puts(const char *str)
\r
451 len = _SysWrite(_stdout, str, len);
\r
452 _SysWrite(_stdout, "\n", 1);
\r
456 EXPORT int vsprintf(char * __s, const char *__format, va_list __args)
\r
458 return vsnprintf(__s, 0x7FFFFFFF, __format, __args);
\r
463 * \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args)
\r
464 * \brief Prints a formatted string to a buffer
\r
465 * \param buf Pointer - Destination Buffer
\r
466 * \param format String - Format String
\r
467 * \param args VarArgs List - Arguments
\r
469 EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list args)
\r
472 int c, minSize, precision, len;
\r
477 int bLongLong, bPadLeft;
\r
479 void _addchar(char ch)
\r
481 if(buf && pos < __maxlen) buf[pos] = ch;
\r
487 while((c = *format++) != 0)
\r
489 // Non-control character
\r
495 // Control Character
\r
497 if(c == '%') { // Literal %
\r
508 // Padding Character
\r
516 minSize = va_arg(args, size_t);
\r
520 if('1' <= c && c <= '9')
\r
523 while('0' <= c && c <= '9')
\r
526 minSize += c - '0';
\r
536 precision = va_arg(args, size_t);
\r
539 else if('1' <= c && c <= '9')
\r
542 while('0' <= c && c <= '9')
\r
545 precision += c - '0';
\r
551 // Check for long long
\r
561 // Just help things along later
\r
568 case 'd': case 'i':
\r
570 if(bLongLong) arg = va_arg(args, int64_t);
\r
571 else arg = va_arg(args, int32_t);
\r
572 itoa(tmp, arg, 10, minSize, pad, 1);
\r
576 // Unsigned Integer
\r
579 if(bLongLong) arg = va_arg(args, uint64_t);
\r
580 else arg = va_arg(args, uint32_t);
\r
581 itoa(tmp, arg, 10, minSize, pad, 0);
\r
590 arg = va_arg(args, intptr_t);
\r
591 itoa(tmp, arg, 16, minSize, pad, 0);
\r
594 // Unsigned Hexadecimal
\r
596 if(bLongLong) arg = va_arg(args, uint64_t);
\r
597 else arg = va_arg(args, uint32_t);
\r
598 itoa(tmp, arg, 16, minSize, pad, 0);
\r
604 if(bLongLong) arg = va_arg(args, uint64_t);
\r
605 else arg = va_arg(args, uint32_t);
\r
606 itoa(tmp, arg, 8, minSize, pad, 0);
\r
612 if(bLongLong) arg = va_arg(args, uint64_t);
\r
613 else arg = va_arg(args, uint32_t);
\r
614 itoa(tmp, arg, 2, minSize, pad, 0);
\r
620 p = va_arg(args, char*);
\r
622 if(!p) p = "(null)";
\r
623 //_SysDebug("vsnprintf: p = '%s'", p);
\r
625 len = strnlen(p, precision);
\r
628 if(bPadLeft) while(minSize > len++) _addchar(pad);
\r
630 if(precision >= 0 && precision -- == 0)
\r
634 if(!bPadLeft) while(minSize > len++) _addchar(pad);
\r
637 // Unknown, just treat it as a character
\r
639 arg = va_arg(args, uint32_t);
\r
647 //_SysDebug("vsnprintf: buf = '%s'", buf);
\r
652 const char cUCDIGITS[] = "0123456789ABCDEF";
\r
654 * \fn static void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned)
\r
655 * \brief Convert an integer into a character string
\r
656 * \param buf Destination Buffer
\r
657 * \param num Number to convert
\r
658 * \param base Base-n number output
\r
659 * \param minLength Minimum length of output
\r
660 * \param pad Padding used to ensure minLength
\r
661 * \param bSigned Signed number output?
\r
663 EXPORT void itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned)
\r
669 if(base > 16 || base < 2) {
\r
674 if(bSigned && (int64_t)num < 0)
\r
681 // Encode into reversed string
\r
682 while(num > base-1) {
\r
683 tmpBuf[pos++] = cUCDIGITS[ num % base ];
\r
684 num = (uint64_t) num / (uint64_t)base; // Shift {number} right 1 digit
\r
687 tmpBuf[pos++] = cUCDIGITS[ num % base ]; // Last digit of {number}
\r
688 if(bSigned) tmpBuf[pos++] = '-'; // Append sign symbol if needed
\r
692 while(minLength-- > 0) buf[i++] = pad;
\r
693 while(pos-- > 0) buf[i++] = tmpBuf[pos]; // Reverse the order of characters
\r
698 * \fn EXPORT int printf(const char *format, ...)
\r
699 * \brief Print a string to stdout
\r
701 EXPORT int printf(const char *format, ...)
\r
707 va_start(args, format);
\r
708 size = vsnprintf(NULL, 0, (char*)format, args);
\r
712 va_start(args, format);
\r
713 vsnprintf(buf, size+1, (char*)format, args);
\r
717 _SysWrite(_stdout, buf, size+1);
\r
726 * \fn EXPORT int sprintf(const char *buf, char *format, ...)
\r
727 * \brief Print a formatted string to a buffer
\r
729 EXPORT int sprintf(char *buf, const char *format, ...)
\r
733 va_start(args, format);
\r
734 ret = vsprintf((char*)buf, (char*)format, args);
\r
740 * \fn EXPORT int snprintf(const char *buf, size_t maxlen, char *format, ...)
\r
741 * \brief Print a formatted string to a buffer
\r
743 EXPORT int snprintf(char *buf, size_t maxlen, const char *format, ...)
\r
747 va_start(args, format);
\r
748 ret = vsnprintf((char*)buf, maxlen, (char*)format, args);
\r