diff --git a/stdio/printf.c b/stdio/printf.c index b9b31b2..8551b4d 100755 --- a/stdio/printf.c +++ b/stdio/printf.c @@ -3,6 +3,7 @@ #include #include #include +#include static bool print(const char * str, size_t len) { const unsigned char * bytes = (const unsigned char *) str; @@ -16,6 +17,174 @@ static bool print(const char * str, size_t len) { return true; } +static bool print_oct(unsigned int strint) { + int i = strint, j = 10; + char str[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + while(j >= 0 && i > 0) { + switch(i % 010) { + case 0: str[j] = '0'; break; + case 1: str[j] = '1'; break; + case 2: str[j] = '2'; break; + case 3: str[j] = '3'; break; + case 4: str[j] = '4'; break; + case 5: str[j] = '5'; break; + case 6: str[j] = '6'; break; + case 7: str[j] = '7'; break; + default: return false; + } + i /= 010; + j--; + } + for(i = 0; str[i] == '\0'; i++) {} + + return print(str+i, 11-i); +} + +static bool print_ptr(void * ptrstr) { + int i = (int) ptrstr, j = 9; + char str[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + while(j >= 2 && i > 0) { + switch(i % 0x10) { + case 0: str[j] = '0'; break; + case 1: str[j] = '1'; break; + case 2: str[j] = '2'; break; + case 3: str[j] = '3'; break; + case 4: str[j] = '4'; break; + case 5: str[j] = '5'; break; + case 6: str[j] = '6'; break; + case 7: str[j] = '7'; break; + case 8: str[j] = '8'; break; + case 9: str[j] = '9'; break; + case 0xA: str[j] = 'A'; break; + case 0xB: str[j] = 'B'; break; + case 0xC: str[j] = 'C'; break; + case 0xD: str[j] = 'D'; break; + case 0xE: str[j] = 'E'; break; + case 0xF: str[j] = 'F'; break; + default: return false; + } + i /= 0x10; + j--; + } + for(i = 0; str[i] == '\0'; i++) {} + + i--; + str[i] = 'x'; + i--; + str[i] = '0'; + + return print(str+i, 10-i); +} + +static bool print_caphex(unsigned int strint) { + int i = strint, j = 7; + char str[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + while(j >= 0 && i > 0) { + switch(i % 0x10) { + case 0: str[j] = '0'; break; + case 1: str[j] = '1'; break; + case 2: str[j] = '2'; break; + case 3: str[j] = '3'; break; + case 4: str[j] = '4'; break; + case 5: str[j] = '5'; break; + case 6: str[j] = '6'; break; + case 7: str[j] = '7'; break; + case 8: str[j] = '8'; break; + case 9: str[j] = '9'; break; + case 0xA: str[j] = 'A'; break; + case 0xB: str[j] = 'B'; break; + case 0xC: str[j] = 'C'; break; + case 0xD: str[j] = 'D'; break; + case 0xE: str[j] = 'E'; break; + case 0xF: str[j] = 'F'; break; + default: return false; + } + i /= 0x10; + j--; + } + for(i = 0; str[i] == '\0'; i++) {} + + return print(str+i, 8-i); +} + +static bool print_hex(unsigned int strint) { + int i = strint, j = 7; + char str[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + while(j >= 0 && i > 0) { + switch(i % 0x10) { + case 0: str[j] = '0'; break; + case 1: str[j] = '1'; break; + case 2: str[j] = '2'; break; + case 3: str[j] = '3'; break; + case 4: str[j] = '4'; break; + case 5: str[j] = '5'; break; + case 6: str[j] = '6'; break; + case 7: str[j] = '7'; break; + case 8: str[j] = '8'; break; + case 9: str[j] = '9'; break; + case 0xA: str[j] = 'a'; break; + case 0xB: str[j] = 'b'; break; + case 0xC: str[j] = 'c'; break; + case 0xD: str[j] = 'd'; break; + case 0xE: str[j] = 'e'; break; + case 0xF: str[j] = 'f'; break; + default: return false; + } + i /= 0x10; + j--; + } + for(i = 0; str[i] == '\0'; i++) {} + + return print(str+i, 8-i); +} + +static bool print_int(int strint) { + int i = strint, j = 10; + char str[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + if(i < 0) { + i = -i; + } + + while(j > 0 && i > 0) { + switch(i % 10) { + case 0: str[j] = '0'; break; + case 1: str[j] = '1'; break; + case 2: str[j] = '2'; break; + case 3: str[j] = '3'; break; + case 4: str[j] = '4'; break; + case 5: str[j] = '5'; break; + case 6: str[j] = '6'; break; + case 7: str[j] = '7'; break; + case 8: str[j] = '8'; break; + case 9: str[j] = '9'; break; + default: return false; + } + i /= 10; + j--; + } + for(i = 0; str[i] == '\0'; i++) {} + + if(strint < 0) { + i--; + str[i] = '-'; + } + + return print(str+i, 11-i); +} + +static bool print_uint(unsigned int strint) { + int i = strint; + if(i < 0) { + i = -i; + } + return print_int(i); +} + int printf(const char * restrict format, ...) { va_list parameters; va_start(parameters, format); @@ -37,7 +206,7 @@ int printf(const char * restrict format, ...) { } if(maxrem < amount) { - /* TODO: Set errno to EOVERFLOW after implementing errno.h */ + errno = EOVERFLOW; return -1; } @@ -58,7 +227,7 @@ int printf(const char * restrict format, ...) { char c = (char) va_arg(parameters, int); if(!maxrem) { - /* TODO: Set errno to EOVERFLOW after implementing errno.h */ + errno = EOVERFLOW; return -1; } @@ -74,7 +243,7 @@ int printf(const char * restrict format, ...) { size_t len = strlen(str); if(maxrem < len) { - /* TODO: Set errno to EOVERFLOW after implementing errno.h */ + errno = EOVERFLOW; return -1; } @@ -84,12 +253,130 @@ int printf(const char * restrict format, ...) { written += len; } + else if(*format == 'd' || *format == 'i') { + format++; + int i = (int) va_arg(parameters, int); + + if(!maxrem) { + errno = EOVERFLOW; + return -1; + } + + if(!print_int(i)) { + return -1; + } + + written += 11; + } + else if(*format == 'u') { + format++; + int i = (int) va_arg(parameters, int); + + if(!maxrem) { + errno = EOVERFLOW; + return -1; + } + + if(!print_uint(i)) { + return -1; + } + + written += 10; + } + else if(*format == 'o') { + format++; + int i = (int) va_arg(parameters, int); + + if(!maxrem) { + errno = EOVERFLOW; + return -1; + } + + if(!print_oct(i)) { + return -1; + } + + written += 11; + } + else if(*format == 'x') { + format++; + int i = (int) va_arg(parameters, int); + + if(!maxrem) { + errno = EOVERFLOW; + return -1; + } + + if(!print_hex(i)) { + return -1; + } + + written += 10; + } + else if(*format == 'X') { + format++; + int i = (int) va_arg(parameters, int); + + if(!maxrem) { + errno = EOVERFLOW; + return -1; + } + + if(!print_caphex(i)) { + return -1; + } + + written += 8; + } + else if(*format == 'p') { + format++; + void * ptr = (void *) va_arg(parameters, void *); + + if(!maxrem) { + errno = EOVERFLOW; + return -1; + } + + if(!print_ptr(ptr)) { + return -1; + } + + /* This is gonna need a change on 64-bit systems. */ + written += 10; + }else if(*format == 'n') { + format++; + + if(!maxrem) { + errno = EOVERFLOW; + return -1; + } + + if(!print_int(written)) { + return -1; + } + + written += 11; + } + else if(*format == '%') { + format++; + + if(!maxrem) { + errno = EOVERFLOW; + return -1; + } + + if(!print("%", 1)) { + return -1; + } + + written++; + } else { format = format_begun_at; size_t len = strlen(format); if(maxrem < len) { - /* TODO: Set errno to EOVERFLOW after implementing errno.h */ + errno = EOVERFLOW; return -1; }