I'm making a hobbyist kernel and I'm trying to implement a printf()
function.
Here's my implementation:
void kprint(uint8_t *format, ...) {
va_list ap;
va_start(ap, format);
uint8_t *ptr;
for (ptr = format; *ptr != '\0'; ptr++) {
if (*ptr == '%') {
ptr++;
switch (*ptr) {
case 's':
puts(va_arg(ap, uint8_t *), 0x0F, xPos, yPos);
break;
}
} else {
puts(ptr, 0x0F, xPos, yPos);
ptr++;
}
}
va_end(ap);
}
When I want to print "Hello World!" using this function it returns me that:
"Hello %sllo %so %sWorld"
Here's function call:
kprint("Hello %s", "World");
the main issue is that you're using puts
to print the rest of the string instead of current char.
} else {
puts(ptr, 0x0F, xPos, yPos);
ptr++;
}
also you're incrementing ptr
when it's already done in the loop. Useful to consume format argument, but not in that case.
A working implementation (not using the strange puts
prototype) that works on a standard system (tested on windows gcc):
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
void zprintf(uint8_t *format, ...)
{
va_list ap;
va_start(ap, format);
uint8_t *ptr;
for (ptr = format; *ptr != '\0'; ptr++) {
if (*ptr == '%') {
ptr++;
switch (*ptr) {
case 's':
fputs(va_arg(ap, uint8_t *),stdout);
break;
case '%':
putchar('%');
break;
}
} else {
putchar(*ptr);
}
}
va_end(ap);
}
int main(){
zprintf("%% Hello %s\n","World");
return 0;
}
prints:
% Hello World
(as a bonus, this implementation handles the escaped %
char)
Using only your special implementation of puts
you could change
} else {
puts(ptr, 0x0F, xPos, yPos);
ptr++;
}
to a working:
} else {
char c[2];
c[0] = *ptr; c[1] = '\0';
puts(c, 0x0F, xPos, yPos);
}
lame but would work :)