Added d, u, o, x, X, p, n, % format specifiers

This commit is contained in:
Gitea 2020-12-01 17:34:35 -06:00
parent 80f7a6ea93
commit b40777bcc4

View file

@ -3,6 +3,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h>
static bool print(const char * str, size_t len) { static bool print(const char * str, size_t len) {
const unsigned char * bytes = (const unsigned char *) str; const unsigned char * bytes = (const unsigned char *) str;
@ -16,6 +17,174 @@ static bool print(const char * str, size_t len) {
return true; 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, ...) { int printf(const char * restrict format, ...) {
va_list parameters; va_list parameters;
va_start(parameters, format); va_start(parameters, format);
@ -37,7 +206,7 @@ int printf(const char * restrict format, ...) {
} }
if(maxrem < amount) { if(maxrem < amount) {
/* TODO: Set errno to EOVERFLOW after implementing errno.h */ errno = EOVERFLOW;
return -1; return -1;
} }
@ -58,7 +227,7 @@ int printf(const char * restrict format, ...) {
char c = (char) va_arg(parameters, int); char c = (char) va_arg(parameters, int);
if(!maxrem) { if(!maxrem) {
/* TODO: Set errno to EOVERFLOW after implementing errno.h */ errno = EOVERFLOW;
return -1; return -1;
} }
@ -74,7 +243,7 @@ int printf(const char * restrict format, ...) {
size_t len = strlen(str); size_t len = strlen(str);
if(maxrem < len) { if(maxrem < len) {
/* TODO: Set errno to EOVERFLOW after implementing errno.h */ errno = EOVERFLOW;
return -1; return -1;
} }
@ -84,12 +253,130 @@ int printf(const char * restrict format, ...) {
written += len; 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 { else {
format = format_begun_at; format = format_begun_at;
size_t len = strlen(format); size_t len = strlen(format);
if(maxrem < len) { if(maxrem < len) {
/* TODO: Set errno to EOVERFLOW after implementing errno.h */ errno = EOVERFLOW;
return -1; return -1;
} }