I am currently attempting to produce a method which I can use like printf within my program but also includes a priority of the log and a source (so I can choose my logging level easily). However my current implementation is going iffy, it can find the first arguement (which has its address cast), however the next ones are completely lost and junk is printed.
Code is adapted from the original at http://www.menie.org/georges/embedded/index.html
Report is the top level function, it converts the std::strings to char* and calls the correct functions. This module also provides the "priority" check.
int Report (std::string format, int priority, std::string source, ...)
{
char* cp_format = const_cast<char*>(format.c_str());
char* cp_source = const_cast<char*>(source.c_str());
register int *varg = (int*) (&cp_format); // source is a better target imo
if (priority <= CURRENT_PRIORITY_LEVEL)
return print (0,varg);
return -1;
}
int print (char** out, int* varg)
{
register int width, pad;
register int pc = 0;
register char* format = (char*)(*varg++);
char scr[2];
// Move past first 2 args to get to list
varg++;
varg++;
// Parse the format component writing out the char's and adding vars.
for ( ; *format != 0; ++format)
{
if (*format == '%')
{
++format;
width = pad = 0;
if (*format == '\0')
break;
if (*format == '%') goto out;
if (*format == '-')
{
++format;
pad = PAD_RIGHT;
}
while (*format == '0')
{
++format;
pad |= PAD_ZERO;
}
for( ; *format >= '0' && *format <= '9'; ++format)
{
width *= 10;
width += *format - '0';
}
if( *format == 's' )
{
register char *s = *((char **)varg++);
pc += prints (out, s?s:"(null)", width, pad);
continue;
}
if( *format == 'd' )
{
pc += printi (out, *varg++, 10, 1, width, pad, 'a');
continue;
}
if( *format == 'x' )
{
pc += printi (out, *varg++, 16, 0, width, pad, 'a');
continue;
}
if( *format == 'X' )
{
pc += printi (out, *varg++, 16, 0, width, pad, 'A');
continue;
}
if( *format == 'u' )
{
pc += printi (out, *varg++, 10, 0, width, pad, 'a');
continue;
}
if( *format == 'c' )
{
/* char are converted to int then pushed on the stack */
scr[0] = *varg++;
scr[1] = '\0';
pc += prints (out, scr, width, pad);
continue;
}
}
else {
out:
printchar (out, *format);
++pc;
}
}
if (out) **out = '\0';
return pc;
}
Print Integers:
#define PRINT_BUF_LEN 12
static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)
{
char print_buf[PRINT_BUF_LEN];
register char *s;
register int t, neg = 0, pc = 0;
register unsigned int u = i;
if (i == 0) {
print_buf[0] = '0';
print_buf[1] = '\0';
return prints (out, print_buf, width, pad);
}
if (sg && b == 10 && i < 0) {
neg = 1;
u = -i;
}
s = print_buf + PRINT_BUF_LEN-1;
*s = '\0';
while (u) {
t = u % b;
if( t >= 10 )
t += letbase - '0' - 10;
*--s = t + '0';
u /= b;
}
if (neg) {
if( width && (pad & PAD_ZERO) ) {
printchar (out, '-');
++pc;
--width;
}
else {
*--s = '-';
}
}
return pc + prints (out, s, width, pad);
}
Print Strings
#define PAD_RIGHT 1
#define PAD_ZERO 2
static int prints(char **out, const char *string, int width, int pad)
{
register int pc = 0, padchar = ' ';
if (width > 0) {
register int len = 0;
register const char *ptr;
for (ptr = string; *ptr; ++ptr) ++len;
if (len >= width) width = 0;
else width -= len;
if (pad & PAD_ZERO) padchar = '0';
}
if (!(pad & PAD_RIGHT)) {
for ( ; width > 0; --width) {
printchar (out, padchar);
++pc;
}
}
for ( ; *string ; ++string) {
printchar (out, *string);
++pc;
}
for ( ; width > 0; --width) {
printchar (out, padchar);
++pc;
}
return pc;
}
Putchars
#define putchar(c) outbyte(c)
static void printchar(char **str, int c)
{
extern int putchar(int c);
if (str) {
**str = c;
++(*str);
}
else (void)putchar(c);
}
I think I might be able to use the original source unmodified (doing varg++ twice seems to result in an unknown error under msvc, however not doing this prints garbage) if I use the address of source rather than the formatting string, but then I need to pass the address of the formatting string as well. I am not really sure where the error occurs or why, my problems occur in the Print function, report passes correctly and the lower level ones (print int, print string, putchar) all function as they should as they are unmodified.
Any hints or thoughts, I did google this however it turns up a lot of people doing stuff with printf (error reporting) and a lot of people implementing stuff, with a printf statement on the page :(.