///\note Initialised in SoMain\r
\r
// === CODE ===\r
+int _fopen_modetoflags(const char *mode)\r
+{\r
+ int flags = 0;\r
+ \r
+ // Get main mode\r
+ switch(*mode)\r
+ {\r
+ case 'r': flags = FILE_FLAG_MODE_READ; break;\r
+ case 'w': flags = FILE_FLAG_MODE_WRITE; break;\r
+ case 'a': flags = FILE_FLAG_MODE_APPEND; break;\r
+ case 'x': flags = FILE_FLAG_MODE_EXEC; break; // Acess addon\r
+ default:\r
+ return -1;\r
+ }\r
+ mode ++;\r
+\r
+ // Get Modifiers\r
+ for( ; *mode; mode ++ )\r
+ {\r
+ switch(*mode)\r
+ {\r
+ case 'b': flags |= FILE_FLAG_M_BINARY; break;\r
+ case '+': flags |= FILE_FLAG_M_EXT; break;\r
+ default:\r
+ return -1;\r
+ }\r
+ }\r
+ \r
+ return flags;\r
+}\r
+\r
/**\r
* \fn FILE *freopen(char *file, char *mode, FILE *fp)\r
*/\r
EXPORT FILE *freopen(const char *file, const char *mode, FILE *fp)\r
{\r
int openFlags = 0;\r
- int i;\r
\r
// Sanity Check Arguments\r
if(!fp || !file || !mode) return NULL;\r
\r
- if(fp->Flags) {\r
+ if(fp->FD != -1) {\r
fflush(fp);\r
- } else\r
- fp->FD = -1;\r
- \r
- // Get main mode\r
- switch(mode[0])\r
- {\r
- case 'r': fp->Flags = FILE_FLAG_MODE_READ; break;\r
- case 'w': fp->Flags = FILE_FLAG_MODE_WRITE; break;\r
- case 'a': fp->Flags = FILE_FLAG_MODE_APPEND; break;\r
- case 'x': fp->Flags = FILE_FLAG_MODE_EXEC; break;\r
- default:\r
- return NULL;\r
- }\r
- // Get Modifiers\r
- for(i=1;mode[i];i++)\r
- {\r
- switch(mode[i])\r
- {\r
- case '+': fp->Flags |= FILE_FLAG_M_EXT;\r
- }\r
}\r
+\r
+ // Get stdio flags\r
+ fp->Flags = _fopen_modetoflags(mode);\r
+ if(fp->Flags == -1)\r
+ return NULL;\r
\r
// Get Open Flags\r
- switch(mode[0])\r
+ switch(fp->Flags & FILE_FLAG_MODE_MASK)\r
{\r
// Read\r
- case 'r': openFlags = OPENFLAG_READ;\r
+ case FILE_FLAG_MODE_READ:\r
+ openFlags = OPENFLAG_READ;\r
if(fp->Flags & FILE_FLAG_M_EXT)\r
openFlags |= OPENFLAG_WRITE;\r
break;\r
// Write\r
- case 'w': openFlags = OPENFLAG_WRITE;\r
+ case FILE_FLAG_MODE_WRITE:\r
+ openFlags = OPENFLAG_WRITE;\r
+ if(fp->Flags & FILE_FLAG_M_EXT)\r
+ openFlags |= OPENFLAG_READ;\r
+ break;\r
+ // Execute\r
+ case FILE_FLAG_MODE_APPEND:\r
+ openFlags = OPENFLAG_APPEND;\r
if(fp->Flags & FILE_FLAG_M_EXT)\r
openFlags |= OPENFLAG_READ;\r
break;\r
// Execute\r
- case 'x': openFlags = OPENFLAG_EXEC;\r
+ case FILE_FLAG_MODE_EXEC:\r
+ openFlags = OPENFLAG_EXEC;\r
break;\r
}\r
\r
return NULL;\r
}\r
\r
- if(mode[0] == 'a') {\r
+ if( (fp->Flags & FILE_FLAG_MODE_MASK) == FILE_FLAG_MODE_APPEND ) {\r
seek(fp->FD, 0, SEEK_END); //SEEK_END\r
}\r
\r
return freopen(file, mode, retFile);\r
}\r
\r
+EXPORT FILE *fmemopen(void *buffer, size_t length, const char *mode)\r
+{\r
+ FILE *ret;\r
+ \r
+ if( !buffer || !mode ) return NULL;\r
+ \r
+ ret = get_file_struct();\r
+ \r
+ ret->FD = -2;\r
+ ret->Flags = _fopen_modetoflags(mode);\r
+ if(ret->Flags == -1) {\r
+ ret->Flags = 0;\r
+ return NULL;\r
+ }\r
+ \r
+ ret->Buffer = buffer;\r
+ ret->BufferStart = 0;\r
+ ret->BufferSize = length;\r
+ \r
+ return ret;\r
+}\r
+\r
EXPORT int fclose(FILE *fp)\r
{\r
- close(fp->FD);\r
+ fflush(fp);\r
+ if( fp->FD != -1 ) {\r
+ close(fp->FD);\r
+ }\r
fp->Flags = 0;\r
fp->FD = -1;\r
return 0;\r
\r
EXPORT void fflush(FILE *fp)\r
{\r
- ///\todo Implement\r
+ if( !fp || fp->FD == -1 )\r
+ return ;\r
+ \r
+ if( !(fp->Flags & FILE_FLAG_DIRTY) )\r
+ return ;\r
+ \r
+ // Nothing to do for memory files\r
+ if( fp->FD == -2 )\r
+ return ;\r
}\r
\r
-EXPORT off_t ftell(FILE *fp)\r
+EXPORT void clearerr(FILE *fp)\r
{\r
- if(!fp || !fp->FD) return -1;\r
+ if( !fp || fp->FD == -1 )\r
+ return ;\r
\r
- return tell(fp->FD);\r
+ // TODO: Impliment clearerr()\r
+}\r
+\r
+EXPORT int feof(FILE *fp)\r
+{\r
+ if( !fp || fp->FD == -1 )\r
+ return 0;\r
+ return !!(fp->Flags & FILE_FLAG_EOF);\r
+}\r
+\r
+EXPORT int ferror(FILE *fp)\r
+{\r
+ if( !fp || fp->FD == -1 )\r
+ return 0;\r
+ return 0;\r
+}\r
+EXPORT int fileno(FILE *stream)\r
+{\r
+ return stream->FD;\r
+}\r
+\r
+EXPORT off_t ftell(FILE *fp)\r
+{\r
+ if(!fp || fp->FD == -1) return -1;\r
+\r
+ if( fp->FD == -2 )\r
+ return fp->Pos; \r
+ else\r
+ return tell(fp->FD);\r
}\r
\r
EXPORT int fseek(FILE *fp, long int amt, int whence)\r
{\r
- if(!fp || !fp->FD) return -1;\r
- \r
- return seek(fp->FD, amt, whence);\r
+ if(!fp || fp->FD == -1) return -1;\r
+\r
+ if( fp->FD == -2 ) {\r
+ switch(whence)\r
+ {\r
+ case SEEK_CUR:\r
+ fp->Pos += amt;\r
+ break;\r
+ case SEEK_SET:\r
+ fp->Pos = amt;\r
+ break;\r
+ case SEEK_END:\r
+ if( fp->BufferSize < (size_t)amt )\r
+ fp->Pos = 0;\r
+ else\r
+ fp->Pos = fp->BufferSize - amt;\r
+ break;\r
+ }\r
+ if(fp->Pos > (off_t)fp->BufferSize) {\r
+ fp->Pos = fp->BufferSize;\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ }\r
+ return 0;\r
+ }\r
+ else\r
+ return seek(fp->FD, amt, whence);\r
}\r
\r
\r
{\r
va_list tmpList;\r
int size;\r
- char sbuf[1024];\r
- char *buf = sbuf;\r
\r
if(!fp || !format) return -1;\r
\r
va_copy(tmpList, args);\r
\r
- size = vsnprintf(sbuf, sizeof(sbuf), (char*)format, tmpList);\r
- \r
- if( size >= sizeof(sbuf) )\r
- {\r
- buf = (char*)malloc(size+1);\r
- if(!buf) {\r
- WRITE_STR(_stdout, "vfprintf ERROR: malloc() failed");\r
- return 0;\r
- }\r
- buf[size] = '\0';\r
- \r
- // Print\r
- vsnprintf(buf, size+1, (char*)format, args);\r
- }\r
+ size = vsnprintf(NULL, 0, (char*)format, tmpList);\r
+ char buf[size+1];\r
+ vsnprintf(buf, size+1, (char*)format, args);\r
\r
// Write to stream\r
- write(fp->FD, buf, size);\r
- \r
- // Free buffer\r
- free(buf);\r
+ fwrite(buf, size, 1, fp);\r
\r
// Return written byte count\r
return size;\r
*/\r
EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)\r
{\r
- int ret;\r
- if(!fp || !fp->FD) return -1;\r
- \r
- ret = write(fp->FD, ptr, size*num);\r
+ size_t ret;\r
+ \r
+ if(!fp || fp->FD == -1)\r
+ return -1;\r
+\r
+ if( fp->FD == -2 ) {\r
+ size_t avail = (fp->BufferSize - fp->Pos) / size;\r
+ if( avail == 0 )\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ if( num > avail ) num = avail;\r
+ size_t bytes = num * size;\r
+ memcpy((char*)fp->Buffer + fp->Pos, ptr, bytes);\r
+ fp->Pos += bytes;\r
+ ret = num;\r
+ }\r
+ else { \r
+ ret = write(fp->FD, ptr, size*num);\r
+ ret /= size;\r
+ }\r
\r
return ret;\r
}\r
*/\r
EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)\r
{\r
- int ret;\r
- if(!fp || !fp->FD) return -1;\r
-\r
- // TODO: Fit the spec better with the return value \r
- ret = read(fp->FD, ptr, size*num);\r
- \r
+ size_t ret;\r
+ \r
+ if(!fp || fp->FD == -1)\r
+ return -1;\r
+\r
+ if( fp->FD == -2 ) {\r
+ size_t avail = (fp->BufferSize - fp->Pos) / size;\r
+ if( avail == 0 )\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ if( num > avail ) num = avail;\r
+ size_t bytes = num * size;\r
+ memcpy(ptr, (char*)fp->Buffer + fp->Pos, bytes);\r
+ fp->Pos += bytes;\r
+ ret = num;\r
+ }\r
+ else {\r
+ ret = read(fp->FD, ptr, size*num);\r
+ ret /= size;\r
+ }\r
+ \r
return ret;\r
}\r
\r
*/\r
EXPORT int fputc(int c, FILE *fp)\r
{\r
- if(!fp || !fp->FD) return -1;\r
- return write(fp->FD, &c, 1);\r
+ return fwrite(&c, 1, 1, fp);\r
}\r
\r
EXPORT int putchar(int c)\r
EXPORT int fgetc(FILE *fp)\r
{\r
char ret = 0;\r
- if(!fp) return -1;\r
- if(read(fp->FD, &ret, 1) == -1) return -1;\r
+ if( fread(&ret, 1, 1, fp) == (size_t)-1 )\r
+ return -1;\r
return ret;\r
}\r
\r
int i;\r
for(i=0;i<STDIO_MAX_STREAMS;i++)\r
{\r
- if(_iob[i].Flags == 0) return &_iob[i];\r
+ if(_iob[i].Flags & FILE_FLAG_ALLOC)\r
+ continue ;\r
+ _iob[i].Flags |= FILE_FLAG_ALLOC;\r
+ _iob[i].FD = -1;\r
+ _iob[i].Pos = 0;\r
+ return &_iob[i];\r
}\r
return NULL;\r
}\r
{\r
char tmp[65];\r
int c, minSize, precision, len;\r
- int pos = 0;\r
+ size_t pos = 0;\r
char *p;\r
char pad;\r
uint64_t arg;\r
*/\r
EXPORT int printf(const char *format, ...)\r
{\r
- #if 1\r
int size;\r
- char sbuf[1024];\r
- char *buf = sbuf;\r
va_list args;\r
\r
// Get final size\r
va_start(args, format);\r
- size = vsnprintf(sbuf, 1024, (char*)format, args);\r
+ size = vsnprintf(NULL, 0, (char*)format, args);\r
+ va_end(args);\r
+ char buf[size+1];\r
+ // Fill Buffer\r
+ va_start(args, format);\r
+ vsnprintf(buf, size+1, (char*)format, args);\r
va_end(args);\r
- \r
- if( size >= 1024 ) {\r
- // Allocate buffer\r
- buf = (char*)malloc(size+1);\r
- if(buf) {\r
- WRITE_STR(_stdout, "PRINTF ERROR: malloc() failed\n");\r
- return 0;\r
- }\r
- buf[size] = '\0';\r
- \r
- // Fill Buffer\r
- va_start(args, format);\r
- vsnprintf(buf, size+1, (char*)format, args);\r
- va_end(args);\r
- }\r
\r
// Send to stdout\r
write(_stdout, buf, size+1);\r
free(buf);\r
// Return\r
return size;\r
- \r
- #else\r
- \r
- int ret;\r
- va_list args;\r
- va_start(args, format);\r
- ret = fprintfv(stdout, (char*)format, args);\r
- va_end(args);\r
- return ret;\r
- #endif\r
}\r
\r
/**\r