Buffer debug output to reduce the number of write() calls and allow to
output information that was logged before the library was initialised.
This commit is contained in:
+58
-31
@@ -24,6 +24,7 @@
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if defined HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
@@ -42,20 +43,24 @@ static void mydebug(char const *format, va_list args);
|
||||
* Helper macro to write an integer value to a given file descriptor,
|
||||
* either in base 10 or in hexadecimal.
|
||||
*/
|
||||
#define WRITE_INT(fd, i, base) \
|
||||
#define WRITE_INT(i, base) \
|
||||
do \
|
||||
{ \
|
||||
char buf[128], *b = buf + 127; \
|
||||
if(i <= 0) \
|
||||
write(fd, (i = -i) ? "-" : "0", 1); /* XXX: hack here */ \
|
||||
append((i = -i) ? "-" : "0", 1); /* XXX: hack here */ \
|
||||
while(i) \
|
||||
{ \
|
||||
*b-- = hex2char[i % base]; \
|
||||
i /= base; \
|
||||
} \
|
||||
write(fd, b + 1, (int)(buf + 127 - b)); \
|
||||
append(b + 1, (int)(buf + 127 - b)); \
|
||||
} while(0)
|
||||
|
||||
/* Temporary buffer for deferred output */
|
||||
char debugbuffer[BUFSIZ];
|
||||
size_t debugcount = 1;
|
||||
|
||||
void _zz_debug(char const *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
@@ -85,23 +90,36 @@ void _zz_debug2(char const *format, ...)
|
||||
* - vfprintf(stderr, format, args);
|
||||
* - fprintf(stderr, "\n");
|
||||
*/
|
||||
static inline void append(void const *data, size_t count)
|
||||
{
|
||||
if (debugcount + count <= sizeof(debugbuffer))
|
||||
{
|
||||
memcpy(debugbuffer + debugcount, data, count);
|
||||
debugcount += count;
|
||||
}
|
||||
}
|
||||
|
||||
static void mydebug(char const *format, va_list args)
|
||||
{
|
||||
static char const *hex2char = "0123456789abcdef";
|
||||
char const *f;
|
||||
int saved_errno;
|
||||
|
||||
if(_zz_debugfd < 0)
|
||||
return;
|
||||
|
||||
saved_errno = errno;
|
||||
|
||||
write(_zz_debugfd, "** zzuf debug ** ", 17);
|
||||
/* If there is spare data and the debug fd is open, we send the data */
|
||||
if (debugcount && _zz_debugfd >= 0)
|
||||
{
|
||||
write(_zz_debugfd, debugbuffer, debugcount);
|
||||
debugcount = 0;
|
||||
}
|
||||
|
||||
append("** zzuf debug ** ", 17);
|
||||
for(f = format; *f; f++)
|
||||
{
|
||||
if(*f != '%')
|
||||
{
|
||||
write(_zz_debugfd, f, 1);
|
||||
append(f, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -113,47 +131,47 @@ static void mydebug(char const *format, va_list args)
|
||||
{
|
||||
char i = (char)(unsigned char)va_arg(args, int);
|
||||
if(i >= 0x20 && i < 0x7f)
|
||||
write(_zz_debugfd, &i, 1);
|
||||
append(&i, 1);
|
||||
else if(i == '\n')
|
||||
write(_zz_debugfd, "\\n", 2);
|
||||
append("\\n", 2);
|
||||
else if(i == '\t')
|
||||
write(_zz_debugfd, "\\t", 2);
|
||||
append("\\t", 2);
|
||||
else if(i == '\r')
|
||||
write(_zz_debugfd, "\\r", 2);
|
||||
append("\\r", 2);
|
||||
else
|
||||
{
|
||||
write(_zz_debugfd, "\\x", 2);
|
||||
write(_zz_debugfd, hex2char + ((i & 0xf0) >> 4), 1);
|
||||
write(_zz_debugfd, hex2char + (i & 0x0f), 1);
|
||||
append("\\x", 2);
|
||||
append(hex2char + ((i & 0xf0) >> 4), 1);
|
||||
append(hex2char + (i & 0x0f), 1);
|
||||
}
|
||||
}
|
||||
else if(*f == 'i' || *f == 'd')
|
||||
{
|
||||
int i = va_arg(args, int);
|
||||
WRITE_INT(_zz_debugfd, i, 10);
|
||||
WRITE_INT(i, 10);
|
||||
}
|
||||
else if(*f == 'x')
|
||||
{
|
||||
int i = va_arg(args, int);
|
||||
WRITE_INT(_zz_debugfd, i, 16);
|
||||
WRITE_INT(i, 16);
|
||||
}
|
||||
else if(f[0] == 'l' && (f[1] == 'i' || f[1] == 'd'))
|
||||
{
|
||||
long int i = va_arg(args, long int);
|
||||
WRITE_INT(_zz_debugfd, i, 10);
|
||||
WRITE_INT(i, 10);
|
||||
f++;
|
||||
}
|
||||
else if(f[0] == 'l' && f[1] == 'l' && (f[2] == 'i' || f[1] == 'd'))
|
||||
{
|
||||
long long int i = va_arg(args, long long int);
|
||||
WRITE_INT(_zz_debugfd, i, 10);
|
||||
WRITE_INT(i, 10);
|
||||
f += 2;
|
||||
}
|
||||
else if(f[0] == 'g')
|
||||
{
|
||||
double g = va_arg(args, double), h = 0.0000001;
|
||||
int i = (int)g;
|
||||
WRITE_INT(_zz_debugfd, i, 10);
|
||||
WRITE_INT(i, 10);
|
||||
for(i = 0; i < 7; i++)
|
||||
{
|
||||
g = (g - (int)g) * 10;
|
||||
@@ -161,46 +179,55 @@ static void mydebug(char const *format, va_list args)
|
||||
if(g < h)
|
||||
break;
|
||||
if(i == 0)
|
||||
write(_zz_debugfd, ".", 1);
|
||||
write(_zz_debugfd, hex2char + (int)g, 1);
|
||||
append(".", 1);
|
||||
append(hex2char + (int)g, 1);
|
||||
}
|
||||
}
|
||||
else if(f[0] == 'p')
|
||||
{
|
||||
uintptr_t i = va_arg(args, uintptr_t);
|
||||
if(!i)
|
||||
write(_zz_debugfd, "NULL", 5);
|
||||
append("NULL", 5);
|
||||
else
|
||||
{
|
||||
write(_zz_debugfd, "0x", 2);
|
||||
WRITE_INT(_zz_debugfd, i, 16);
|
||||
append("0x", 2);
|
||||
WRITE_INT(i, 16);
|
||||
}
|
||||
}
|
||||
else if(f[0] == 's')
|
||||
{
|
||||
char *s = va_arg(args, char *);
|
||||
if(!s)
|
||||
write(_zz_debugfd, "(nil)", 5);
|
||||
append("(nil)", 5);
|
||||
else
|
||||
{
|
||||
int l = 0;
|
||||
while(s[l])
|
||||
l++;
|
||||
write(_zz_debugfd, s, l);
|
||||
append(s, l);
|
||||
}
|
||||
}
|
||||
else if(f[0] == '0' && f[1] == '2' && f[2] == 'x')
|
||||
{
|
||||
int i = va_arg(args, int);
|
||||
write(_zz_debugfd, hex2char + ((i & 0xf0) >> 4), 1);
|
||||
write(_zz_debugfd, hex2char + (i & 0x0f), 1);
|
||||
append(hex2char + ((i & 0xf0) >> 4), 1);
|
||||
append(hex2char + (i & 0x0f), 1);
|
||||
f += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
write(_zz_debugfd, f - 1, 2);
|
||||
append(f - 1, 2);
|
||||
}
|
||||
}
|
||||
write(_zz_debugfd, "\n", 1);
|
||||
append("\n", 1);
|
||||
|
||||
/* If the debug fd is open, we send the data */
|
||||
if (_zz_debugfd >= 0)
|
||||
{
|
||||
write(_zz_debugfd, debugbuffer, debugcount);
|
||||
debugcount = 0;
|
||||
}
|
||||
|
||||
errno = saved_errno;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user