/*\r
-AcessOS Basic C Library\r
-*/\r
+ * AcessOS Basic C Library\r
+ * stdio.c\r
+ */\r
#include "config.h"\r
#include <acess/sys.h>\r
#include <stdlib.h>\r
#include <stdio.h>\r
+#include <string.h>\r
+#include "lib.h"\r
#include "stdio_int.h"\r
\r
#define DEBUG_BUILD 0\r
\r
// === CONSTANTS ===\r
+#define _stdin 0\r
+#define _stdout 1\r
\r
// === PROTOTYPES ===\r
+EXPORT void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned);\r
struct sFILE *get_file_struct();\r
\r
// === GLOBALS ===\r
struct sFILE _iob[STDIO_MAX_STREAMS]; // IO Buffer\r
+struct sFILE *stdin; // Standard Input\r
+struct sFILE *stdout; // Standard Output\r
+struct sFILE *stderr; // Standard Error\r
+///\note Initialised in SoMain\r
\r
// === CODE ===\r
/**\r
* \fn FILE *freopen(FILE *fp, char *file, char *mode)\r
*/\r
-FILE *freopen(FILE *fp, char *file, char *mode)\r
+EXPORT FILE *freopen(FILE *fp, char *file, char *mode)\r
{\r
int openFlags = 0;\r
int i;\r
\param file String - Filename to open\r
\param mode Mode to open in\r
*/\r
-FILE *fopen(char *file, char *mode)\r
+EXPORT FILE *fopen(char *file, char *mode)\r
{\r
FILE *retFile;\r
\r
return freopen(retFile, file, mode);\r
}\r
\r
-void fclose(FILE *fp)\r
+EXPORT void fclose(FILE *fp)\r
{\r
close(fp->FD);\r
free(fp);\r
}\r
\r
-void fflush(FILE *fp)\r
+EXPORT void fflush(FILE *fp)\r
{\r
///\todo Implement\r
}\r
\r
/**\r
- * \fn int fprintf(FILE *fp, const char *format, ...)\r
- * \brief Print a formatted string to a stream\r
+ * \fn EXPORT int vfprintf(FILE *fp, const char *format, va_list args)\r
+ * \brief Print to a file from a variable argument list\r
*/\r
-int fprintf(FILE *fp, const char *format, ...)\r
+EXPORT int vfprintf(FILE *fp, const char *format, va_list args)\r
{\r
+ va_list tmpList = args;\r
int size;\r
char *buf;\r
- va_list args;\r
- \r
+ \r
if(!fp || !format) return -1;\r
\r
- // Get Size\r
- va_start(args, format);\r
- size = ssprintfv((char*)format, args);\r
- va_end(args);\r
+ size = vsprintf(NULL, (char*)format, tmpList);\r
\r
- // Allocate buffer\r
buf = (char*)malloc(size+1);\r
buf[size] = '\0';\r
\r
// Print\r
- va_start(args, format);\r
- sprintfv(buf, (char*)format, args);\r
- va_end(args);\r
+ vsprintf(buf, (char*)format, args);\r
\r
// Write to stream\r
write(fp->FD, size+1, buf);\r
return size;\r
}\r
\r
+/**\r
+ * \fn int fprintf(FILE *fp, const char *format, ...)\r
+ * \brief Print a formatted string to a stream\r
+ */\r
+EXPORT int fprintf(FILE *fp, const char *format, ...)\r
+{\r
+ va_list args;\r
+ int ret;\r
+ \r
+ // Get Size\r
+ va_start(args, format);\r
+ ret = vfprintf(fp, (char*)format, args);\r
+ va_end(args);\r
+ \r
+ return ret;\r
+}\r
+\r
+/**\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, size*num, ptr);\r
+ \r
+ return ret;\r
+}\r
+\r
+/**\r
+ * \fn EXPORT int fputc(int c, FILE *fp)\r
+ * \brief Write a single character to the stream\r
+ */\r
+EXPORT int fputc(int c, FILE *fp)\r
+{\r
+ if(!fp || !fp->FD) return -1;\r
+ return write(fp->FD, 1, &c);\r
+}\r
+\r
+/**\r
+ * \fn EXPORT int fgetc(FILE *fp)\r
+ * \brief Read a character from the stream\r
+ */\r
+EXPORT int fgetc(FILE *fp)\r
+{\r
+ int ret = 0;\r
+ if(!fp) return -1;\r
+ if(read(fp->FD, 1, &ret) == -1) return -1;\r
+ return ret;\r
+}\r
+\r
// --- INTERNAL ---\r
/**\r
* \fn FILE *get_file_struct()\r
}\r
return NULL;\r
}\r
+\r
+EXPORT int putchar(int ch)\r
+{\r
+ return write(_stdout, 1, (char*)&ch);\r
+}\r
+\r
+EXPORT int puts(const char *str)\r
+{\r
+ int len;\r
+ \r
+ if(!str) return 0;\r
+ len = strlen(str);\r
+ \r
+ len = write(_stdout, len, (char*)str);\r
+ write(_stdout, 1, "\n");\r
+ return len;\r
+}\r
+\r
+//sprintfv\r
+/**\r
+ \fn EXPORT void vsprintf(char *buf, const char *format, va_list args)\r
+ \brief Prints a formatted string to a buffer\r
+ \param buf Pointer - Destination Buffer\r
+ \param format String - Format String\r
+ \param args VarArgs List - Arguments\r
+*/\r
+EXPORT int vsprintf(char *buf, const char *format, va_list args)\r
+{\r
+ char tmp[33];\r
+ int c, minSize;\r
+ int pos = 0;\r
+ char *p;\r
+ char pad;\r
+ uint64_t arg;\r
+ int bLongLong;\r
+\r
+ tmp[32] = '\0';\r
+ \r
+ while((c = *format++) != 0)\r
+ {\r
+ // Non-control character\r
+ if (c != '%') {\r
+ if(buf) buf[pos] = c;\r
+ pos ++;\r
+ continue;\r
+ }\r
+ \r
+ // Control Character\r
+ c = *format++;\r
+ if(c == '%') { // Literal %\r
+ if(buf) buf[pos] = '%';\r
+ pos ++;\r
+ continue;\r
+ }\r
+ \r
+ // Padding\r
+ if(c == '0') {\r
+ pad = '0';\r
+ c = *format++;\r
+ } else\r
+ pad = ' ';\r
+ minSize = 0;\r
+ if('1' <= c && c <= '9')\r
+ {\r
+ while('0' <= c && c <= '9')\r
+ {\r
+ minSize *= 10;\r
+ minSize += c - '0';\r
+ c = *format++;\r
+ }\r
+ }\r
+ \r
+ // Check for long long\r
+ bLongLong = 0;\r
+ if(c == 'l')\r
+ {\r
+ c = *format++;\r
+ if(c == 'l') {\r
+ bLongLong = 1;\r
+ }\r
+ }\r
+ \r
+ p = tmp;\r
+ \r
+ // Get Type\r
+ switch( c )\r
+ {\r
+ // Signed Integer\r
+ case 'd': case 'i':\r
+ // Get Argument\r
+ if(bLongLong) arg = va_arg(args, int64_t);\r
+ else arg = va_arg(args, int32_t);\r
+ itoa(tmp, arg, 10, minSize, pad, 1);\r
+ goto sprintf_puts;\r
+ \r
+ // Unsigned Integer\r
+ case 'u':\r
+ // Get Argument\r
+ if(bLongLong) arg = va_arg(args, uint64_t);\r
+ else arg = va_arg(args, uint32_t);\r
+ itoa(tmp, arg, 10, minSize, pad, 0);\r
+ goto sprintf_puts;\r
+ \r
+ // Pointer\r
+ case 'p':\r
+ if(buf) {\r
+ buf[pos] = '*';\r
+ buf[pos+1] = '0';\r
+ buf[pos+2] = 'x';\r
+ }\r
+ pos += 3;\r
+ // Fall through to hex\r
+ // Unsigned Hexadecimal\r
+ case 'x':\r
+ if(bLongLong) arg = va_arg(args, uint64_t);\r
+ else arg = va_arg(args, uint32_t);\r
+ itoa(tmp, arg, 16, minSize, pad, 0);\r
+ goto sprintf_puts;\r
+ \r
+ // Unsigned Octal\r
+ case 'o':\r
+ if(bLongLong) arg = va_arg(args, uint64_t);\r
+ else arg = va_arg(args, uint32_t);\r
+ itoa(tmp, arg, 8, minSize, pad, 0);\r
+ goto sprintf_puts;\r
+ \r
+ // Unsigned binary\r
+ case 'b':\r
+ if(bLongLong) arg = va_arg(args, uint64_t);\r
+ else arg = va_arg(args, uint32_t);\r
+ itoa(tmp, arg, 2, minSize, pad, 0);\r
+ goto sprintf_puts;\r
+\r
+ // String\r
+ case 's':\r
+ arg = va_arg(args, uint32_t);\r
+ p = (void*)(intptr_t)arg;\r
+ sprintf_puts:\r
+ if(!p) p = "(null)";\r
+ if(buf) {\r
+ while(*p) {\r
+ buf[pos++] = *p++;\r
+ }\r
+ }\r
+ else {\r
+ while(*p) {\r
+ pos++; p++;\r
+ }\r
+ }\r
+ break;\r
+\r
+ // Unknown, just treat it as a character\r
+ default:\r
+ arg = va_arg(args, uint32_t);\r
+ if(buf) buf[pos] = arg;\r
+ pos ++;\r
+ break;\r
+ }\r
+ }\r
+ if(buf) buf[pos] = '\0';\r
+ \r
+ return pos;\r
+}\r
+\r
+const char cUCDIGITS[] = "0123456789ABCDEF";\r
+/**\r
+ * \fn static void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned)\r
+ * \brief Convert an integer into a character string\r
+ */\r
+EXPORT void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned)\r
+{\r
+ char tmpBuf[32];\r
+ int pos=0, i;\r
+\r
+ if(!buf) return;\r
+ if(base > 16) {\r
+ buf[0] = 0;\r
+ return;\r
+ }\r
+ \r
+ if(bSigned && (int64_t)num < 0)\r
+ {\r
+ num = -num;\r
+ bSigned = 1;\r
+ } else\r
+ bSigned = 0;\r
+ \r
+ while(num > base-1) {\r
+ tmpBuf[pos] = cUCDIGITS[ num % base ];\r
+ num = (long) num / base; // Shift {number} right 1 digit\r
+ pos++;\r
+ }\r
+\r
+ tmpBuf[pos++] = cUCDIGITS[ num % base ]; // Last digit of {number}\r
+ if(bSigned) tmpBuf[pos++] = '-'; // Append sign symbol if needed\r
+ i = 0;\r
+ minLength -= pos;\r
+ while(minLength-- > 0) buf[i++] = pad;\r
+ while(pos-- > 0) buf[i++] = tmpBuf[pos]; // Reverse the order of characters\r
+ buf[i] = 0;\r
+}\r
+\r
+/**\r
+ * \fn EXPORT int printf(const char *format, ...)\r
+ * \brief Print a string to stdout\r
+ */\r
+EXPORT int printf(const char *format, ...)\r
+{\r
+ #if 1\r
+ int size;\r
+ char *buf;\r
+ va_list args;\r
+ \r
+ // Get final size\r
+ va_start(args, format);\r
+ size = vsprintf(NULL, (char*)format, args);\r
+ va_end(args);\r
+ \r
+ // Allocate buffer\r
+ buf = (char*)malloc(size+1);\r
+ buf[size] = '\0';\r
+ \r
+ // Fill Buffer\r
+ va_start(args, format);\r
+ vsprintf(buf, (char*)format, args);\r
+ va_end(args);\r
+ \r
+ // Send to stdout\r
+ write(_stdout, size+1, buf);\r
+ \r
+ // Free buffer\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
+ * \fn EXPORT int sprintf(const char *buf, char *format, ...)\r
+ * \brief Print a formatted string to a buffer\r
+ */\r
+EXPORT int sprintf(char *buf, const char *format, ...)\r
+{\r
+ int ret;\r
+ va_list args;\r
+ va_start(args, format);\r
+ ret = vsprintf((char*)buf, (char*)format, args);\r
+ va_end(args);\r
+ return ret;\r
+}\r