Files
ZPU/software/common/small_printf.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