#include <stdarg.h>
#ifdef TARGET
# include "angel.h"
# include "devconf.h"
#else
# include "host.h"
#endif
#include "logging.h"
#ifndef UNUSED
# define UNUSED(x) ((x)=(x))
#endif
#ifdef DEBUG
# ifdef DEBUG_METHOD
# define STRINGIFY2(x) #x
# define STRINGIFY(x) STRINGIFY2(x)
# define DEBUG_METHOD_HEADER STRINGIFY(DEBUG_METHOD##.h)
# include DEBUG_METHOD_HEADER
# define METHOD_EXPAND_2(m, p, c) m##p(c)
# define METHOD_EXPAND(m, p, c) METHOD_EXPAND_2(m, p, c)
# define CHAROUT(c) METHOD_EXPAND(DEBUG_METHOD, _PutChar, (c))
# define PRE_DEBUG(l) METHOD_EXPAND(DEBUG_METHOD, _PreWarn, (l))
# define POST_DEBUG(n) METHOD_EXPAND(DEBUG_METHOD, _PostWarn, (n))
# else
# error Must define DEBUG_METHOD
# endif
#endif
#pragma no_check_stack
#ifdef DEBUG
static const char hextab[] = "0123456789ABCDEF";
static int va_warn0(char *format, va_list args)
{
int len = 0;
while ((format != NULL) && (*format != '\0'))
{
if (*format == '%')
{
char fch = *(++format);
int ival;
char *string;
int width = 0;
int padzero = FALSE;
if ((fch >= '0') && (fch <= '9'))
{
if (fch == '0')
{
padzero = TRUE;
fch = *(++format);
}
while ((fch >= '0') && (fch <= '9'))
{
width = ((width * 10) + (fch - '0'));
fch = *(++format);
}
}
if (fch == 'l')
fch = *(++format);
switch (fch)
{
case 'c':
ival = va_arg(args, int);
CHAROUT((char)ival);
len++;
break;
case 'x':
case 'X':
{
unsigned int uval = va_arg(args, unsigned int);
int loop;
UNUSED(uval);
if ((width == 0) || (width > 8))
width = 8;
for(loop = (width * 4); (loop != 0); loop -= 4)
{
CHAROUT(hextab[(uval >> (loop - 4)) & 0xF]);
len++;
}
}
break;
case 'd':
ival = va_arg(args, int);
if (ival < 0)
{
ival = -ival;
CHAROUT('-');
len++;
}
if (ival == 0)
{
CHAROUT('0');
len++;
}
else
{
char buffer[16];
int count = 0;
while (ival != 0)
{
buffer[count++] = ('0' + ((unsigned int)ival % 10));
ival = ((unsigned int)ival / 10);
}
if (width != 0)
{
width -= count;
for (; (width != 0); width--)
{
CHAROUT(padzero ? '0': ' ');
len++;
}
}
for (; (count != 0); count--)
{
CHAROUT(buffer[count - 1]);
len++;
}
}
break;
case 's':
string = va_arg(args, char *);
if (string != NULL)
while (*string)
{
CHAROUT(*string);
len++;
string++;
}
break;
case '\0':
format--;
break;
default:
CHAROUT(*format);
len++;
break;
}
format++;
}
else
{
CHAROUT(*format);
len++;
format++;
}
}
return len;
}
# ifdef DEBUG_NEED_VA_WARN1
static void va_warn1(int len, char *msg)
{
UNUSED(len); UNUSED(msg);
}
# endif
void va_warn(WarnLevel level, char *format, va_list args)
{
int len;
if ( PRE_DEBUG( level ) )
{
len = va_warn0(format, args);
POST_DEBUG( len );
}
}
#else
void va_warn(WarnLevel level, char *format, va_list args)
{
UNUSED(level); UNUSED(format); UNUSED(args);
}
#endif
#pragma check_stack
#pragma no_check_stack
void __rt_warning(char *format, ...)
{
va_list args;
va_start(args, format);
va_warn(WL_WARN, format, args);
va_end(args);
return;
}
#pragma check_stack
#ifdef TARGET
#pragma no_check_stack
void __rt_uninterruptable_loop( void );
void __rt_error(char *format, ...)
{
va_list args;
va_start(args, format);
va_warn(WL_ERROR, format, args);
__rt_uninterruptable_loop();
va_end(args);
return;
}
#pragma check_stack
#endif
#ifdef DO_TRACE
static bool trace_on = FALSE;
#pragma no_check_stack
void __rt_trace(char *format, ...)
{
va_list args;
if (trace_on)
{
va_start(args, format);
va_warn(WL_TRACE, format, args);
va_end(args);
}
return;
}
#pragma check_stack
#endif