📄 _printf.c
字号:
#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "_stdio.h"
#if defined(MINIMAL_PRINTF) && !defined(INTONLY_PRINTF)
#define INTONLY_PRINTF
#endif
#if defined(FLOAT_PRINTF) && defined(_AVR) && !defined(ATMEGA)
/* this wouldn't fit on a small target otherwise */
#define INTONLY_PRINTF
#endif
/* we need to keep track of how many characters are written out, as the return
* value to this function
*/
#define PUT1CHAR(c) (*_put)(c), ret++
#ifndef _PRINT
#define _PRINT _print
#define ATOI atoi
#define XCONST const
#endif
/* make this static to lessen the load on the local stack
*/
static char buf[25];
int
_PRINT(void (*_put)(char), XCONST char *fmt, va_list va)
{
char *bp;
char *s;
char carray[2];
int i;
int ret = 0;
int flags;
char signch;
int done;
#if defined(_AVR)
FLASH char *cs;
#endif
#if !defined(MINIMAL_PRINTF)
int width;
int prec;
#endif
#if !defined(INTONLY_PRINTF)
long l;
#endif
/* process each charcater in format string */
for ( ; *fmt; fmt++)
{
if (*fmt != '%')
{
PUT1CHAR(*fmt);
continue;
}
/* got a % code, parse and perform action
*/
#if !defined(MINIMAL_PRINTF)
width = 0;
prec = -1;
#endif
flags = 0;
bp = buf;
signch = ' ';
++fmt;
#if !defined(MINIMAL_PRINTF)
/* check for the presence of flag characters: */
for (done = 0; ; fmt++)
{
switch (fmt[0])
{
case '#':
flags |= F_ALTFORM;
break;
case '-':
flags |= F_LEFTALIGN;
break;
case '+':
flags |= F_ADDSIGN;
signch = '+';
break;
case ' ':
flags |= F_ADDSIGN;
signch = ' ';
break;
case '0':
flags |= F_ZEROPADD;
break;
default:
done = 1;
break;
}
if (done) /* break here so fmt++ would not happen */
break;
}
/* read the 'width' and 'precision' fields: */
if (isdigit (fmt[0]))
{
width = ATOI ((char *) fmt);
while (isdigit (*fmt))
fmt++;
}
else if (fmt[0] == '*')
{
width = va_arg(va, int);
fmt++;
}
if (fmt[0] == '.')
{
++fmt;
if (isdigit(fmt[0]))
{
prec = ATOI ((char *) fmt);
while (isdigit (*fmt))
fmt++;
}
else if (fmt[0] == '*')
{
prec = va_arg(va, int);
fmt++;
}
}
if (fmt[0] == 'l')
{
++fmt;
flags |= F_LONG;
}
#endif
/* look for the base conversion type: */
switch (*fmt)
{
default:
PUT1CHAR(*fmt);
break;
case 'd':
case 'i':
#ifndef INTONLY_PRINTF
if (flags & F_LONG)
{
l = va_arg (va, long);
ltoa (bp, l, 10);
}
else
#endif
{
i = va_arg (va, int);
itoa (bp, i, 10);
}
goto print_digits;
case 'u':
case 'o':
case 'x':
case 'X':
case 'p':
#ifndef INTONLY_PRINTF
if (flags & F_LONG)
l = va_arg (va, unsigned long);
else
#endif
i = va_arg (va, unsigned int);
if (*fmt == 'u')
{
#ifndef INTONLY_PRINTF
if (flags & F_LONG)
ultoa (bp, l, 10);
else
#endif
utoa (bp, i, 10);
}
else if (*fmt == 'o')
{
#if !defined(MINIMAL_PRINTF)
if (flags & F_ALTFORM)
*bp++ = '0';
#endif
#ifndef INTONLY_PRINTF
if (flags & F_LONG)
ultoa (bp, l, 8);
else
#endif
utoa (bp, i, 8);
}
else
{
if (fmt[0] == 'p')
{
*bp++ = '0';
*bp++ = 'x';
}
#if !defined(MINIMAL_PRINTF)
else if (flags & F_ALTFORM)
{
*bp++ = '0';
*bp++ = fmt[0];
}
#endif
#if !defined(INTONLY_PRINTF)
if (flags & F_LONG)
ultoa (bp, l, 16);
else
#endif
utoa (bp, i, 16);
if (fmt[0] == 'X')
for (s = buf; *s; s++)
*s = toupper(*s);
}
print_digits:
s = buf;
#if !defined(MINIMAL_PRINTF)
if (prec == -1)
prec = 0;
if (prec)
{
i = strlen(buf);
if (prec < i)
prec = i;
}
#endif
goto print_string;
case 'c':
carray[0] = va_arg (va, int);
#if !defined(MINIMAL_PRINTF)
if (width > 1)
{
prec = width;
carray[1] = 0;
s = carray;
goto print_string;
}
else
#endif
PUT1CHAR(carray[0]);
break;
#if defined(_AVR)
case 'S':
cs = va_arg(va, __flash char *);
print_cstring:
#define SPTR cs
#define STRLEN cstrlen
#include "_printf_string.c"
#undef SPTR
#undef STRLEN
break;
#endif
case 's':
s = va_arg (va, char *);
if (!s)
{
static FLASH char err[] = { "(null ptr passed)" };
#if defined(_AVR)
cs = err;
goto print_cstring;
#else
s = (char *)err;
#endif
}
print_string:
#define SPTR s
#define STRLEN strlen
#include "_printf_string.c"
#undef SPTR
#undef STRLEN
break;
#ifdef FLOAT_PRINTF
{
#include "formatfp1.h"
float f;
int fpcode;
case 'e': fpcode = FMT_SCIENTIFIC; goto print_float;
case 'E': fpcode = FMT_SCIENTIFIC_BIG_E; goto print_float;
case 'f': fpcode = FMT_NORMAL; goto print_float;
case 'g': fpcode = FMT_OPTIMUM; goto print_float;
case 'G': fpcode = FMT_OPTIMUM_BIG_E; goto print_float;
print_float:
f = va_arg(va, float);
if (prec == -1)
prec = 6;
s = _FormatFP_1(buf, fpcode, f, flags, width, prec);
while (*s)
PUT1CHAR(*s++);
}
#else
case 'f':
case 'e':
case 'E': {
static FLASH char err[] = {
"integer only printf, select Project->Options->Target,"
"\"FP printf\" to print floating point numbers>"
};
#if defined(_AVR)
cs = err;
goto print_cstring;
#else
s = (char *)err;
goto print_string;
#endif
}
#endif
}
}
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -