#include <l4/types.h>
#include <stdarg.h>
#include <l4io.h>
#ifndef NULL
#define NULL ((void *) 0)
#endif
extern "C" int __l4_printf (const char *fmt, ...);
extern "C" int l4_printf (const char *fmt, ...)
__attribute__ ((weak, alias ("__l4_printf")));
extern "C" int __l4_vprintf (const char *fmt, va_list);
extern "C" int l4_vprintf (const char *fmt, va_list)
__attribute__ ((weak, alias ("__l4_vprintf")));
extern "C" int __l4_snprintf (char *str, L4_Size_t size, const char *fmt, ...);
extern "C" int l4_snprintf (char *str, L4_Size_t size, const char *fmt, ...)
__attribute__ ((weak, alias ("__l4_snprintf")));
extern "C" int __l4_vsnprintf (char *str, L4_Size_t size, const char *fmt, va_list);
extern "C" int l4_vsnprintf (char *str, L4_Size_t size, const char *fmt, va_list)
__attribute__ ((weak, alias ("__l4_vsnprintf")));
extern "C" int __l4_puts (const char * str);
extern "C" int l4_puts (const char * str)
__attribute__ ((weak, alias ("__l4_puts")));
static int strlen (const char * s);
static void print_string (const char * s);
int __l4_puts (const char * str)
{
print_string (str);
l4_putchar ('\n');
return strlen (str);
}
static int strlen (const char * s)
{
int n;
for ( n = 0; *s++ != '\0'; n++ )
;
return n;
}
static void print_string (const char * s)
{
while(*s)
l4_putchar(*s++);
}
int __l4_vsnprintf(char *str, L4_Size_t size, const char *fmt, va_list ap)
{
char convert[64];
int f_left, f_sign, f_space, f_zero, f_alternate;
int f_long, f_short, f_ldouble;
int width, precision;
int i, c, base, sign, signch, numdigits, numpr = 0, someflag;
unsigned long uval, uval2;
char *digits, *string, *p = str;
L4_ThreadId_t tid;
#define PUTCH(ch) do { \
if ( size-- <= 0 ) \
goto Done; \
*p++ = (ch); \
} while (0)
#define PUTSTR(st) do { \
char *s = (st); \
while ( *s != '\0' ) { \
if ( size-- <= 0 ) \
goto Done; \
*p++ = *s++; \
} \
} while (0)
#define PUTDEC(num) do { \
uval = num; \
numdigits = 0; \
do { \
convert[ numdigits++ ] = digits[ uval % 10 ]; \
uval /= 10; \
} while ( uval > 0 ); \
while ( numdigits > 0 ) \
PUTCH( convert[--numdigits] ); \
} while (0)
#define LEFTPAD(num) do { \
int cnt = (num); \
if ( ! f_left && cnt > 0 ) \
while ( cnt-- > 0 ) \
PUTCH( f_zero ? '0' : ' ' ); \
} while (0)
#define RIGHTPAD(num) do { \
int cnt = (num); \
if ( f_left && cnt > 0 ) \
while ( cnt-- > 0 ) \
PUTCH( ' ' ); \
} while (0)
size--;
if ( fmt == NULL ) {
PUTSTR( "(null fmt string)" );
goto Done;
}
while ( size > 0 ) {
while ( (c = *fmt++) != '%' ) {
if ( size-- <= 0 || c == '\0' )
goto Done;
*p++ = c;
}
f_left = f_sign = f_space = f_zero = f_alternate = 0;
someflag = 1;
while ( someflag ) {
switch ( *fmt ) {
case '-': f_left = 1; fmt++; break;
case '+': f_sign = 1; fmt++; break;
case ' ': f_space = 1; fmt++; break;
case '0': f_zero = 1; fmt++; break;
case '#': f_alternate = 1; fmt++; break;
default: someflag = 0; break;
}
}
if ( (c = *fmt) == '*' ) {
width = va_arg( ap, int );
fmt++;
} else if ( c >= '0' && c <= '9' ) {
width = 0;
while ( (c = *fmt++) >= '0' && c <= '9' ) {
width *= 10;
width += c - '0';
}
fmt--;
} else {
width = -1;
}
if ( *fmt == '.' ) {
if ( (c = *++fmt) == '*' ) {
precision = va_arg( ap, int );
fmt++;
} else if ( c >= '0' && c <= '9' ) {
precision = 0;
while ( (c = *fmt++) >= '0' && c <= '9' ) {
precision *= 10;
precision += c - '0';
}
fmt--;
} else {
precision = -1;
}
} else {
precision = -1;
}
f_long = f_short = f_ldouble = 0;
switch ( *fmt ) {
case 'h': f_short = 1; fmt++; break;
case 'l': f_long = 1; fmt++; break;
case 'L': f_ldouble = 1; fmt++; break;
}
sign = 1;
switch ( c = *fmt++ ) {
case 'b':
uval = f_long ? va_arg( ap, long ) : va_arg( ap, int );
base = 2;
digits = "01";
goto Print_unsigned;
case 'o':
uval = f_long ? va_arg( ap, long ) : va_arg( ap, int );
base = 8;
digits = "012345678";
goto Print_unsigned;
case 'p':
precision = width = sizeof (long) * 2;
f_alternate = 1;
if (sizeof (void *) == sizeof (long))
f_long = 1;
case 'x':
uval = f_long ? va_arg( ap, long ) : va_arg( ap, int );
base = 16;
digits = "0123456789abcdef";
goto Print_unsigned;
case 'X':
uval = f_long ? va_arg( ap, long ) : va_arg( ap, int );
base = 16;
digits = "0123456789ABCDEF";
goto Print_unsigned;
case 'd':
case 'i':
uval = f_long ? va_arg( ap, long ) : va_arg( ap, int );
base = 10;
digits = "0123456789";
goto Print_signed;
case 'u':
uval = f_long ? va_arg( ap, long ) : va_arg( ap, int );
base = 10;
digits = "0123456789";
Print_unsigned:
sign = 0;
Print_signed:
signch = 0;
uval2 = uval;
if ( sign ) {
if ( f_sign && (long) uval >= 0 ) {
signch = '+';
} else if ( f_space && (long) uval >= 0 ) {
signch = ' ';
} else if ( (long) uval < 0 ) {
signch = '-';
uval = -( (long) uval );
}
}
if (sizeof (long) >= 8 && base == 16)
{
numdigits = 0;
do {
convert[numdigits++] = digits[uval & 0xf];
uval /= 16;
} while ( uval > 0 );
}
else
{
numdigits = 0;
do {
convert[numdigits++] = digits[(unsigned int) uval % base];
uval /= base;
} while ( uval > 0 );
}
numpr = numdigits > precision ? numdigits : precision;
if ( signch )
numpr++;
if ( f_alternate ) {
if ( base == 8 )
numpr++;
else if ( base == 16 || base == 2 )
numpr += 2;
}
if ( ! f_left && width > numpr ) {
if ( f_zero ) {
numpr = width;
} else {
for ( i = width - numpr; i > 0; i-- )
PUTCH(' ');
}
}
if ( signch ) {
PUTCH( signch );
numpr--;
}
if ( f_alternate ) {
if ( base == 2 ) {
numpr--;
PUTCH('%');
} else if ( base == 8 ) {
numpr--;
PUTCH('0');
} else if ( base == 16 ) {
numpr -= 2;
PUTSTR("0x");
}
}
for ( i = numpr - numdigits; i > 0; i-- )
PUTCH('0');
while ( numdigits > 0 )
PUTCH( convert[--numdigits] );
RIGHTPAD( width - numpr - (signch ? 1 : 0) );
break;
#if !defined(L4_ARCH_ALPHA)
case 'f':
{
double fval = va_arg( ap, double );
if ( precision == -1 )
precision = 6;
if ( f_sign && fval >= 0.0 ) {
signch = '+';
} else if ( f_space && fval >= 0.0 ) {
signch = ' ';
} else if ( fval < 0.0 ) {
signch = '-';
fval = -fval;
} else {
signch = 0;
}
uval = (unsigned long) fval;
numdigits = 0;
do {
convert[ numdigits++ ] = '0' + uval % 10;
uval /= 10;
} while ( uval > 0 );
numpr = numdigits + (signch ? 1 : 0);
if ( precision > 0 )
numpr += 1 + precision;
LEFTPAD( width - numpr );
if ( signch )
PUTCH( signch );
while ( numdigits > 0 )
PUTCH( convert[--numdigits] );
if ( precision > 0 ) {
while ( fval >= 1.0 )
fval -= (double) (unsigned long) fval;
PUTCH('.');
while ( precision-- > 0 ) {
fval *= 10.0;
uval = (unsigned long) fval;
PUTCH( '0' + uval );
fval -= (double) (unsigned long) fval;
}
}
RIGHTPAD( width - numpr );
break;
}
#endif
case 't':
tid = va_arg( ap, L4_ThreadId_t );
if ( L4_IsNilThread(tid) ) {
PUTSTR("NIL_ID");
break;
}
digits = "0123456789";
if (L4_IsGlobalId(tid))
{
PUTSTR("GlobThread=");
PUTDEC(tid.global.X.thread_no);
PUTSTR(",ver=");
PUTDEC(tid.global.X.version);
}
else if (L4_IsLocalId(tid))
{
PUTSTR("LocThread=");
PUTDEC(tid.local.X.local_id);
}
else {
PUTSTR("? ");
PUTDEC(tid.raw);
}
break;
case 's':
string = va_arg( ap, char * );
if ( string == NULL ) {
PUTSTR( "(null)" );
break;
}
if ( width > 0 ) {
numpr = strlen( string );
if ( precision >= 0 && precision < numpr )
numpr = precision;
LEFTPAD( width - numpr );
}
if ( precision >= 0 ) {
while ( precision-- > 0 && (c = *string++) != '\0' )
PUTCH( c );
} else {
while ( (c = *string++) != '\0' )
PUTCH( c );
}
RIGHTPAD( width - numpr );
break;
case 'c':
PUTCH( va_arg( ap, int ) );
break;
case '%':
PUTCH('%');
break;
case 'n':
*(va_arg( ap, int * )) = p - str;
break;
default:
PUTCH('%');
PUTCH(c);
break;
}
}
Done:
*p = '\0';
return p - str;
}
int __l4_snprintf(char *str, L4_Size_t size, const char *fmt, ...)
{
va_list ap;
int r;
if ( fmt == NULL )
return 0;
va_start(ap, fmt);
r = l4_vsnprintf(str, size, fmt, ap);
va_end(ap);
return r;
}
int __l4_printf(const char *fmt, ...)
{
char outbuf[256];
va_list ap;
int r;
if ( fmt == NULL )
return 0;
va_start(ap, fmt);
r = l4_vsnprintf(outbuf, sizeof(outbuf), fmt, ap);
va_end(ap);
if ( r > 0 )
print_string(outbuf);
return r;
}
int __l4_vprintf(const char *fmt, va_list ap)
{
char outbuf[256];
int r;
if ( fmt == NULL )
return 0;
r = l4_vsnprintf(outbuf, sizeof(outbuf), fmt, ap);
if ( r > 0 )
print_string(outbuf);
return r;
}