184 lines
3.3 KiB
C
184 lines
3.3 KiB
C
|
|
#include <stdarg.h>
|
|
|
|
int putchar(int c);
|
|
|
|
#ifndef DISABLE_PRINTF
|
|
|
|
static char temp[80];
|
|
|
|
static int
|
|
_cvt(int val, char *buf, int radix)
|
|
{
|
|
#ifdef PRINTF_HEX_ONLY
|
|
int c;
|
|
int i;
|
|
int nz=0;
|
|
// if(val<0)
|
|
// {
|
|
// putchar('-');
|
|
// val=-val;
|
|
// }
|
|
if(val)
|
|
{
|
|
for(i=0;i<8;++i)
|
|
{
|
|
c=(val>>28)&0xf;
|
|
val<<=4;
|
|
if(c)
|
|
nz=1; // Non-zero? Start printing then.
|
|
if(c>9)
|
|
c+='A'-10;
|
|
else
|
|
c+='0';
|
|
if(nz) // If we've encountered only zeroes so far we don't print.
|
|
putchar(c);
|
|
}
|
|
}
|
|
else
|
|
putchar('0');
|
|
return(0);
|
|
#else
|
|
char *cp = temp;
|
|
const char *digits="0123456789ABCDEF";
|
|
int length = 0;
|
|
|
|
if(val<0)
|
|
{
|
|
putchar('-');
|
|
val=-val;
|
|
}
|
|
if (val == 0) {
|
|
/* Special case */
|
|
*cp++ = '0';
|
|
} else {
|
|
while (val) {
|
|
unsigned int c;
|
|
c=val%radix;
|
|
*cp++ = digits[c];
|
|
val /= radix;
|
|
}
|
|
}
|
|
while (cp != temp) {
|
|
*buf++ = *--cp;
|
|
length++;
|
|
}
|
|
*buf = '\0';
|
|
return (length);
|
|
#endif
|
|
}
|
|
|
|
#define is_digit(c) ((c >= '0') && (c <= '9'))
|
|
|
|
|
|
static char vpfbuf[sizeof(long long)*8];
|
|
|
|
static int
|
|
_vprintf(const char *fmt, va_list ap)
|
|
{
|
|
unsigned int c;
|
|
int sign;
|
|
int *s2;
|
|
char *cp=vpfbuf;
|
|
int left_prec, right_prec, zero_fill, pad, pad_on_right,
|
|
i, islong, islonglong;
|
|
unsigned int val = 0;
|
|
int res = 0, length = 0;
|
|
int nextfmt;
|
|
|
|
// Because we haven't implemented loadb from ROM yet, we can't use *<char*>++.
|
|
// We work around this by reading 32 bits at a time and shift/masking the bytes
|
|
// individually.
|
|
// This is only necessary if using the hardware implementation of the
|
|
// loadb/storeb instructions and running from BlockRAM. Loadb/storeb from external
|
|
// RAM is implemented.
|
|
|
|
s2=(int*)fmt;
|
|
nextfmt=0;
|
|
do
|
|
{
|
|
int i;
|
|
int cs=*s2++;
|
|
for(i=0;i<4;++i)
|
|
{
|
|
char tmp[2];
|
|
c=(cs>>24)&0xff;
|
|
cs<<=8;
|
|
if(c==0)
|
|
return(res);
|
|
|
|
if(nextfmt) // Have we encountered a %?
|
|
{
|
|
nextfmt=0;
|
|
left_prec = right_prec = pad_on_right = islong = islonglong = 0;
|
|
sign = '\0';
|
|
// Fetch value [numeric descriptors only]
|
|
switch (c) {
|
|
case 'd':
|
|
case 'x':
|
|
val = (long)va_arg(ap, unsigned int);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
// Process output
|
|
switch (c) {
|
|
case 'd':
|
|
length = _cvt(val, vpfbuf, 10);
|
|
cp = vpfbuf;
|
|
break;
|
|
case 'x':
|
|
length = _cvt(val, vpfbuf, 16);
|
|
cp = vpfbuf;
|
|
break;
|
|
case 's':
|
|
cp = va_arg(ap, char *);
|
|
puts(cp);
|
|
length = 0;
|
|
break;
|
|
case 'c':
|
|
c = va_arg(ap, int /*char*/);
|
|
putchar(c);
|
|
res++;
|
|
continue;
|
|
default:
|
|
putchar('%');
|
|
putchar(c);
|
|
res += 2;
|
|
continue;
|
|
}
|
|
while (length-- > 0) {
|
|
c = *cp++;
|
|
putchar(c);
|
|
res++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (c == '%')
|
|
nextfmt=1;
|
|
else
|
|
{
|
|
putchar(c);
|
|
res++;
|
|
}
|
|
}
|
|
}
|
|
} while(c);
|
|
}
|
|
|
|
|
|
int
|
|
small_printf(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
int ret;
|
|
|
|
va_start(ap, fmt);
|
|
ret = _vprintf(fmt, ap);
|
|
va_end(ap);
|
|
return (ret);
|
|
}
|
|
#endif
|
|
|