158 lines
4.2 KiB
C
158 lines
4.2 KiB
C
/*------------------------------------------------------------------------/
|
|
/ Universal string handler for user console interface
|
|
/-------------------------------------------------------------------------/
|
|
/
|
|
/ Copyright (C) 2011, ChaN, all right reserved.
|
|
/
|
|
/ * This software is a free software and there is NO WARRANTY.
|
|
/ * No restriction on use. You can use, modify and redistribute it for
|
|
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
|
|
/ * Redistributions of source code must retain the above copyright notice.
|
|
/
|
|
/-------------------------------------------------------------------------*/
|
|
|
|
#include "../include/xprintf.h"
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
void (*xfunc_out)(unsigned char); /* Pointer to the output stream */
|
|
static char *outptr;
|
|
|
|
/*----------------------------------------------*/
|
|
/* Put a character */
|
|
/*----------------------------------------------*/
|
|
|
|
void xputc (char c)
|
|
{
|
|
if (_CR_CRLF && c == '\n') xputc('\r'); /* CR -> CRLF */
|
|
|
|
if (outptr) {
|
|
*outptr++ = (unsigned char)c;
|
|
return;
|
|
}
|
|
|
|
if (xfunc_out) xfunc_out((unsigned char)c);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------*/
|
|
/* Put a null-terminated string */
|
|
/*----------------------------------------------*/
|
|
|
|
void xputs ( /* Put a string to the default device */
|
|
const char* str /* Pointer to the string */
|
|
)
|
|
{
|
|
while (*str)
|
|
xputc(*str++);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------*/
|
|
/* Formatted string output */
|
|
/*----------------------------------------------*/
|
|
/* xprintf("%d", 1234); "1234"
|
|
xprintf("%6d,%3d%%", -200, 5); " -200, 5%"
|
|
xprintf("%-6u", 100); "100 "
|
|
xprintf("%ld", 12345678L); "12345678"
|
|
xprintf("%04x", 0xA3); "00a3"
|
|
xprintf("%08LX", 0x123ABC); "00123ABC"
|
|
xprintf("%016b", 0x550F); "0101010100001111"
|
|
xprintf("%s", "String"); "String"
|
|
xprintf("%-4s", "abc"); "abc "
|
|
xprintf("%4s", "abc"); " abc"
|
|
xprintf("%c", 'a'); "a"
|
|
xprintf("%f", 10.0); <xprintf lacks floating point support>
|
|
*/
|
|
|
|
static
|
|
void xvprintf (
|
|
const char* fmt, /* Pointer to the format string */
|
|
va_list arp /* Pointer to arguments */
|
|
)
|
|
{
|
|
unsigned int r, i, j, w, f;
|
|
unsigned long v;
|
|
char s[16], c, d, *p;
|
|
|
|
|
|
for (;;) {
|
|
c = *fmt++; /* Get a char */
|
|
if (!c) break; /* End of format? */
|
|
if (c != '%') { /* Pass through it if not a % sequense */
|
|
xputc(c); continue;
|
|
}
|
|
f = 0;
|
|
c = *fmt++; /* Get first char of the sequense */
|
|
if (c == '0') { /* Flag: '0' padded */
|
|
f = 1; c = *fmt++;
|
|
} else {
|
|
if (c == '-') { /* Flag: left justified */
|
|
f = 2; c = *fmt++;
|
|
}
|
|
}
|
|
for (w = 0; c >= '0' && c <= '9'; c = *fmt++) /* Minimum width */
|
|
w = w * 10 + c - '0';
|
|
if (c == 'l' || c == 'L') { /* Prefix: Size is long int */
|
|
f |= 4; c = *fmt++;
|
|
}
|
|
if (!c) break; /* End of format? */
|
|
d = c;
|
|
if (d >= 'a') d -= 0x20;
|
|
switch (d) { /* Type is... */
|
|
case 'S' : /* String */
|
|
p = va_arg(arp, char*);
|
|
for (j = 0; p[j]; j++) ;
|
|
while (!(f & 2) && j++ < w) xputc(' ');
|
|
xputs(p);
|
|
while (j++ < w) xputc(' ');
|
|
continue;
|
|
case 'C' : /* Character */
|
|
xputc((char)va_arg(arp, int)); continue;
|
|
case 'B' : /* Binary */
|
|
r = 2; break;
|
|
case 'O' : /* Octal */
|
|
r = 8; break;
|
|
case 'D' : /* Signed decimal */
|
|
case 'U' : /* Unsigned decimal */
|
|
r = 10; break;
|
|
case 'X' : /* Hexdecimal */
|
|
r = 16; break;
|
|
default: /* Unknown type (passthrough) */
|
|
xputc(c); continue;
|
|
}
|
|
|
|
/* Get an argument and put it in numeral */
|
|
v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int));
|
|
if (d == 'D' && (v & 0x80000000)) {
|
|
v = 0 - v;
|
|
f |= 8;
|
|
}
|
|
i = 0;
|
|
do {
|
|
d = (char)(v % r); v /= r;
|
|
if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
|
|
s[i++] = d + '0';
|
|
} while (v && i < sizeof(s));
|
|
if (f & 8) s[i++] = '-';
|
|
j = i; d = (f & 1) ? '0' : ' ';
|
|
while (!(f & 2) && j++ < w) xputc(d);
|
|
do xputc(s[--i]); while(i);
|
|
while (j++ < w) xputc(' ');
|
|
}
|
|
}
|
|
|
|
void xprintf ( /* Put a formatted string to the default device */
|
|
const char* fmt, /* Pointer to the format string */
|
|
... /* Optional arguments */
|
|
)
|
|
{
|
|
va_list arp;
|
|
|
|
|
|
va_start(arp, fmt);
|
|
xvprintf(fmt, arp);
|
|
va_end(arp);
|
|
}
|