Added d, u, o, x, X, p, n, % format specifiers
This commit is contained in:
parent
80f7a6ea93
commit
b40777bcc4
1 changed files with 291 additions and 4 deletions
295
stdio/printf.c
295
stdio/printf.c
|
@ -3,6 +3,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue