X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Flibc.so_src%2FfileIO.c;h=441e72e070c1b8a678a7a467e26aa1302fcffb58;hb=f4e3c3d24ca880fe72396b2b0fc1ca3ce506b6ff;hp=1b1d3f38bbf305055123f0d8ea18d744d5435e45;hpb=b98fbd4e9c71447d81fc9bd643fb174c76346e0f;p=tpg%2Facess2.git diff --git a/Usermode/Libraries/libc.so_src/fileIO.c b/Usermode/Libraries/libc.so_src/fileIO.c index 1b1d3f38..441e72e0 100644 --- a/Usermode/Libraries/libc.so_src/fileIO.c +++ b/Usermode/Libraries/libc.so_src/fileIO.c @@ -10,6 +10,8 @@ #include "lib.h" #include "stdio_int.h" +#define WRITE_STR(_fd, _str) write(_fd, _str, sizeof(_str)) + #define DEBUG_BUILD 0 // === CONSTANTS === @@ -17,7 +19,7 @@ #define _stdout 1 // === PROTOTYPES === -EXPORT void itoa(char *buf, uint64_t num, uint base, int minLength, char pad, int bSigned); +EXPORT void itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned); struct sFILE *get_file_struct(); // === GLOBALS === @@ -80,7 +82,7 @@ EXPORT FILE *freopen(const char *file, const char *mode, FILE *fp) case 'x': openFlags = OPENFLAG_EXEC; break; } - + //Open File if(fp->FD != -1) fp->FD = reopen(fp->FD, file, openFlags); @@ -116,10 +118,12 @@ EXPORT FILE *fopen(const char *file, const char *mode) return freopen(file, mode, retFile); } -EXPORT void fclose(FILE *fp) +EXPORT int fclose(FILE *fp) { close(fp->FD); - free(fp); + fp->Flags = 0; + fp->FD = -1; + return 0; } EXPORT void fflush(FILE *fp) @@ -127,7 +131,7 @@ EXPORT void fflush(FILE *fp) ///\todo Implement } -EXPORT long int ftell(FILE *fp) +EXPORT off_t ftell(FILE *fp) { if(!fp || !fp->FD) return -1; @@ -148,20 +152,22 @@ EXPORT int fseek(FILE *fp, long int amt, int whence) */ EXPORT int vfprintf(FILE *fp, const char *format, va_list args) { - va_list tmpList = args; + va_list tmpList; int size; char sbuf[1024]; char *buf = sbuf; - + if(!fp || !format) return -1; + + va_copy(tmpList, args); - size = vsnprintf(sbuf, 1024, (char*)format, tmpList); + size = vsnprintf(sbuf, sizeof(sbuf), (char*)format, tmpList); - if( size >= 1024 ) + if( size >= sizeof(sbuf) ) { buf = (char*)malloc(size+1); if(!buf) { - write(_stdout, 31, "vfprintf ERROR: malloc() failed"); + WRITE_STR(_stdout, "vfprintf ERROR: malloc() failed"); return 0; } buf[size] = '\0'; @@ -171,7 +177,7 @@ EXPORT int vfprintf(FILE *fp, const char *format, va_list args) } // Write to stream - write(fp->FD, size, buf); + write(fp->FD, buf, size); // Free buffer free(buf); @@ -206,7 +212,7 @@ EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp) int ret; if(!fp || !fp->FD) return -1; - ret = write(fp->FD, size*num, ptr); + ret = write(fp->FD, ptr, size*num); return ret; } @@ -219,8 +225,9 @@ EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp) { int ret; if(!fp || !fp->FD) return -1; - - ret = read(fp->FD, size*num, ptr); + + // TODO: Fit the spec better with the return value + ret = read(fp->FD, ptr, size*num); return ret; } @@ -232,7 +239,13 @@ EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp) EXPORT int fputc(int c, FILE *fp) { if(!fp || !fp->FD) return -1; - return write(fp->FD, 1, &c); + return write(fp->FD, &c, 1); +} + +EXPORT int putchar(int c) +{ + c &= 0xFF; + return write(_stdout, &c, 1); } /** @@ -241,9 +254,16 @@ EXPORT int fputc(int c, FILE *fp) */ EXPORT int fgetc(FILE *fp) { - int ret = 0; + char ret = 0; if(!fp) return -1; - if(read(fp->FD, 1, &ret) == -1) return -1; + if(read(fp->FD, &ret, 1) == -1) return -1; + return ret; +} + +EXPORT int getchar(void) +{ + char ret = 0; + if(read(_stdin, &ret, 1) != 1) return -1; return ret; } @@ -262,20 +282,15 @@ FILE *get_file_struct() return NULL; } -EXPORT int putchar(int ch) -{ - return write(_stdout, 1, (char*)&ch); -} - -EXPORT int puts(const char *str) +EXPORT int puts(const char *str) { int len; if(!str) return 0; len = strlen(str); - len = write(_stdout, len, (char*)str); - write(_stdout, 1, "\n"); + len = write(_stdout, str, len); + write(_stdout, "\n", 1); return len; } @@ -286,21 +301,27 @@ EXPORT int vsprintf(char * __s, const char *__format, va_list __args) //sprintfv /** - \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args) - \brief Prints a formatted string to a buffer - \param buf Pointer - Destination Buffer - \param format String - Format String - \param args VarArgs List - Arguments -*/ + * \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args) + * \brief Prints a formatted string to a buffer + * \param buf Pointer - Destination Buffer + * \param format String - Format String + * \param args VarArgs List - Arguments + */ EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list args) { char tmp[65]; - int c, minSize; + int c, minSize, precision, len; int pos = 0; char *p; char pad; uint64_t arg; - int bLongLong; + int bLongLong, bPadLeft; + + void _addchar(char ch) + { + if(buf && pos < __maxlen) buf[pos] = ch; + pos ++; + } tmp[32] = '\0'; @@ -308,34 +329,64 @@ EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list arg { // Non-control character if (c != '%') { - if(buf && pos < __maxlen) buf[pos] = c; - pos ++; + _addchar(c); continue; } // Control Character c = *format++; if(c == '%') { // Literal % - if(buf && pos < __maxlen) buf[pos] = '%'; - pos ++; + _addchar('%'); continue; } - // Padding + bPadLeft = 0; + bLongLong = 0; + minSize = 0; + precision = -1; + pad = ' '; + + // Padding Character if(c == '0') { pad = '0'; c = *format++; - } else - pad = ' '; - minSize = 0; - if('1' <= c && c <= '9') - { - while('0' <= c && c <= '9') + } + // Padding length + if( c == '*' ) { + // Variable length + minSize = va_arg(args, size_t); + c = *format++; + } + else { + if('1' <= c && c <= '9') { - minSize *= 10; - minSize += c - '0'; + minSize = 0; + while('0' <= c && c <= '9') + { + minSize *= 10; + minSize += c - '0'; + c = *format++; + } + } + } + + // Precision + if(c == '.') { + c = *format++; + if(c == '*') { + precision = va_arg(args, size_t); c = *format++; } + else if('1' <= c && c <= '9') + { + precision = 0; + while('0' <= c && c <= '9') + { + precision *= 10; + precision += c - '0'; + c = *format++; + } + } } // Check for long long @@ -347,7 +398,8 @@ EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list arg bLongLong = 1; } } - + + // Just help things along later p = tmp; // Get Type @@ -359,6 +411,7 @@ EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list arg if(bLongLong) arg = va_arg(args, int64_t); else arg = va_arg(args, int32_t); itoa(tmp, arg, 10, minSize, pad, 1); + precision = -1; goto sprintf_puts; // Unsigned Integer @@ -367,25 +420,24 @@ EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list arg if(bLongLong) arg = va_arg(args, uint64_t); else arg = va_arg(args, uint32_t); itoa(tmp, arg, 10, minSize, pad, 0); + precision = -1; goto sprintf_puts; // Pointer case 'p': - if(buf && pos+2 < __maxlen) { - buf[pos] = '*'; - buf[pos+1] = '0'; - buf[pos+2] = 'x'; - } - pos += 3; - arg = va_arg(args, uint32_t); + _addchar('*'); + _addchar('0'); + _addchar('x'); + arg = va_arg(args, intptr_t); itoa(tmp, arg, 16, minSize, pad, 0); + precision = -1; goto sprintf_puts; - // Fall through to hex // Unsigned Hexadecimal case 'x': if(bLongLong) arg = va_arg(args, uint64_t); else arg = va_arg(args, uint32_t); itoa(tmp, arg, 16, minSize, pad, 0); + precision = -1; goto sprintf_puts; // Unsigned Octal @@ -393,6 +445,7 @@ EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list arg if(bLongLong) arg = va_arg(args, uint64_t); else arg = va_arg(args, uint32_t); itoa(tmp, arg, 8, minSize, pad, 0); + precision = -1; goto sprintf_puts; // Unsigned binary @@ -400,37 +453,37 @@ EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list arg if(bLongLong) arg = va_arg(args, uint64_t); else arg = va_arg(args, uint32_t); itoa(tmp, arg, 2, minSize, pad, 0); + precision = -1; goto sprintf_puts; // String case 's': - arg = va_arg(args, uint32_t); - p = (void*)(intptr_t)arg; + p = va_arg(args, char*); sprintf_puts: if(!p) p = "(null)"; //_SysDebug("vsnprintf: p = '%s'", p); - if(buf) { - while(*p) { - if(pos < __maxlen) buf[pos] = *p; - pos ++; p ++; - } - } - else { - while(*p) { - pos++; p++; - } + if(precision >= 0) + len = strnlen(p, precision); + else + len = strlen(p); + if(bPadLeft) while(minSize > len++) _addchar(pad); + while( *p ) { + if(precision >= 0 && precision -- == 0) + break; + _addchar(*p++); } + if(!bPadLeft) while(minSize > len++) _addchar(pad); break; // Unknown, just treat it as a character default: arg = va_arg(args, uint32_t); - if(buf && pos < __maxlen) buf[pos] = arg; - pos ++; + _addchar(arg); break; } - } - if(buf && pos < __maxlen) buf[pos] = '\0'; + } + _addchar('\0'); + pos --; //_SysDebug("vsnprintf: buf = '%s'", buf); @@ -441,6 +494,12 @@ const char cUCDIGITS[] = "0123456789ABCDEF"; /** * \fn static void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned) * \brief Convert an integer into a character string + * \param buf Destination Buffer + * \param num Number to convert + * \param base Base-n number output + * \param minLength Minimum length of output + * \param pad Padding used to ensure minLength + * \param bSigned Signed number output? */ EXPORT void itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned) { @@ -460,6 +519,7 @@ EXPORT void itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, } else bSigned = 0; + // Encode into reversed string while(num > base-1) { tmpBuf[pos++] = cUCDIGITS[ num % base ]; num = (uint64_t) num / (uint64_t)base; // Shift {number} right 1 digit @@ -496,7 +556,7 @@ EXPORT int printf(const char *format, ...) // Allocate buffer buf = (char*)malloc(size+1); if(buf) { - write(_stdout, 29, "PRINTF ERROR: malloc() failed"); + WRITE_STR(_stdout, "PRINTF ERROR: malloc() failed\n"); return 0; } buf[size] = '\0'; @@ -508,7 +568,7 @@ EXPORT int printf(const char *format, ...) } // Send to stdout - write(_stdout, size+1, buf); + write(_stdout, buf, size+1); // Free buffer free(buf); @@ -539,3 +599,17 @@ EXPORT int sprintf(char *buf, const char *format, ...) va_end(args); return ret; } + +/** + * \fn EXPORT int snprintf(const char *buf, size_t maxlen, char *format, ...) + * \brief Print a formatted string to a buffer + */ +EXPORT int snprintf(char *buf, size_t maxlen, const char *format, ...) +{ + int ret; + va_list args; + va_start(args, format); + ret = vsnprintf((char*)buf, maxlen, (char*)format, args); + va_end(args); + return ret; +}