While I was working with an 8K flash MCU, I found that the default printf provided by 'C' library occupies close to 1.8K (too much eh?). I decided to create a function of my own which generates approximately 850 Bytes of code. Posting it for my own reference and for others to use it
WARNING: I'm not responsible for the code if it cause night blindness to your pet DOG!
/**
* @file Minimal printf source file
* @author Sundarapandian A
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdarg.h>
#define F_UNS 1
#define F_BIG 2
#define F_ZERO 4
#define IBUFSZ 16
/* pputc function */
void pputc(int ch);
/* Print an integer in given format */
static int iprint(unsigned long int val, int flag, int prec, int base)
{
static const char *lt = "0123456789ABCDEF";
char buf[IBUFSZ];
int i, j, neg = 0;
if (!(flag & F_UNS) && (int) val < 0) {
neg = 1;
val = -val;
}
for (i = IBUFSZ - 1; i >= 0; i--) {
buf[i] = lt[val - ((val / base) * base)];
val = val / base;
if (!val)
break;
}
for (j = 0; j < prec - (IBUFSZ - i + neg); j++) {
pputc((flag & F_ZERO) ? '0' : ' ');
}
if (neg) {
pputc('-');
}
j = IBUFSZ - i + neg;
for (; i < IBUFSZ; i++)
pputc((flag & F_BIG) ? buf[i] : (buf[i] | 0x20));
return prec > j ? prec : j;
}
/**
* Minimal printf (Without floating point support)
*/
int min_printf(const char *fmt, ...)
{
int apr = 0, pflag = 0, prec = 0, cnt = 0;
va_list ap;
const char *str;
va_start(ap, fmt);
for (; *fmt; fmt++) {
if (!apr && *fmt == '%') {
apr = 1;
prec = pflag = 0;
continue;
}
if (!apr) {
pputc(*fmt);
cnt++;
continue;
}
switch (*fmt) {
case '%':
pputc('%');
cnt++;
apr = 0;
break;
case '0':
if (!prec)
pflag |= F_ZERO;
else
prec *= 10;
break;
case 's':
str = va_arg(ap, const char *);
while (*str) {
pputc(*str++);
cnt++;
}
apr = 0;
break;
case '#':
case 'l':
break;
case 'u':
cnt += iprint(va_arg(ap, unsigned int),
pflag | F_UNS, prec, 10);
apr = 0;
break;
case 'c':
pputc(va_arg(ap, int));
cnt++;
apr = 0;
break;
case 'd':
cnt += iprint(va_arg(ap, long int), pflag, prec, 10);
apr = 0;
break;
case 'X':
pflag |= F_BIG;
case 'x':
cnt += iprint(va_arg(ap, unsigned int),
pflag | F_UNS, prec, 16);
apr = 0;
break;
case '*':
prec = va_arg(ap, int);
break;
default:
if (*fmt >= '1' && *fmt <= '9') {
prec = (prec * 10) + (*fmt - '0');
} else {
/* Something wrong */
apr = 0;
}
} /* End of switch */
} /* End of for loop */
va_end(ap);
return cnt;
}
#define TESTING
#ifdef TESTING
#include <stdio.h>
/**
* Function to print a char on terminal/file
*/
void pputc(int ch)
{
putchar(ch);
}
int main()
{
int val;
val = min_printf("0x%0*X %8d %lu %s %c\r\n",
8, 10, -567, (unsigned long int) -4,
"Test Str", 0x41);
min_printf("Num chars printed on screen: %d\r\n", val);
return 0;
}
#endif
No comments:
Post a Comment