Files
QNX/lib/c/stdio/xprintf.c
2025-08-20 19:02:58 +08:00

138 lines
3.4 KiB
C

/* _Printf function */
#include <ctype.h>
#include <string.h>
#include "xstdio.h"
#include "xwchar.h"
_STD_BEGIN
#if __EDG__ /* compiler test */
#undef stderr
extern FILE _Stderr;
FILE *stderr = &_Stderr; /* displace any other stderr */
#endif /* __EDG__ */
int _Printf(void *(*pfn)(void *, const char *, size_t),
void *arg, const char *fmt, va_list ap_arg)
{ /* print formatted */
_Pft x;
_Mbstinit(mbst);
va_list ap;
_Vacopy(&ap, ap_arg);
x.pfn = pfn, x.arg = arg, x.nchar = 0;
for (; ; )
{ /* scan format string */
for (; ; )
{ /* copy any literal text */
int m, n;
wchar_t wc = L'\0';
if ((n = _Mbtowc(&wc, fmt, INT_MAX, &mbst)) <= 0)
n = *fmt == '\0' ? 0 : 1; /* bad parse, eat one char */
if ((m = (wc == L'%' ? n - 1 : n)) <= 0)
;
else if ((x.arg = (*x.pfn)(x.arg, fmt, m)) == 0)
return (EOF);
else
x.nchar += m;
fmt += n;
if (wc == L'%')
break;
else if (wc == L'\0')
return (x.nchar);
}
{ /* process a conversion specifier */
const char *t;
static const char fchar[] = " +-#0" /* %v additions */ ",;:_";
static const unsigned int fbit[] = {
_FSP, _FPL, _FMI, _FNO, _FZE, 0};
#define FBIT_SIZE ((sizeof (fbit) - 1) / sizeof (fbit[0]))
x.n0 = x.nz0 = x.n1 = x.nz1 = x.n2 = x.nz2 = 0;
#if _HAS_FIXED_POINT
x.sep = ' ';
for (x.flags = 0; (t = strchr(&fchar[0], *fmt)) != 0; ++fmt)
{ /* store either a flag or a %v separator */
size_t idx = t - &fchar[0];
if (idx < FBIT_SIZE)
x.flags |= fbit[t - &fchar[0]];
else
x.sep = *fmt;
}
#else /* _HAS_FIXED_POINT */
for (x.flags = 0; (t = memchr(&fchar[0], *fmt, FBIT_SIZE)) != 0;
++fmt)
x.flags |= fbit[t - &fchar[0]];
#endif /* _HAS_FIXED_POINT */
if (*fmt == '*')
{ /* get width argument */
x.width = va_arg(ap, int);
if (x.width < 0)
{ /* same as '-' flag */
x.width = -x.width;
x.flags |= _FMI;
}
++fmt;
}
else /* accumulate width digits */
for (x.width = 0; isdigit((unsigned char)*fmt); ++fmt)
if (x.width < _WMAX)
x.width = x.width * 10 + (unsigned char)*fmt - '0';
if (*fmt != '.')
x.prec = -1;
else if (*++fmt == '*')
{ /* get precision argument */
x.prec = va_arg(ap, int);
++fmt;
}
else /* accumulate precision digits */
for (x.prec = 0; isdigit((unsigned char)*fmt); ++fmt)
if (x.prec < _WMAX)
x.prec = x.prec * 10 + (unsigned char)*fmt - '0';
#ifdef __QNX__
x.qual = (char)(strchr("hjltzLq", *fmt) ? *fmt++ : '\0');
#else
x.qual = (char)(strchr("hjltzL", *fmt) ? *fmt++ : '\0');
#endif
#if _HAS_FIXED_POINT
if (x.qual == '\0' && *fmt == 'v')
x.qual = *fmt++; /* 'v', 'vh', or 'vl' */
if (x.qual == 'h' && *fmt == 'v'
|| x.qual == 'v' && *fmt == 'h')
x.qual = 'w', ++fmt; /* 'w' is 'hv' or 'vh' */
else if (x.qual == 'l' && *fmt == 'v'
|| x.qual == 'v' && *fmt == 'l')
x.qual = 'W', ++fmt; /* 'W' is 'lv' or 'vl' */
else
#endif /* _HAS_FIXED_POINT */
if (x.qual == 'h' && *fmt == 'h')
x.qual = 'b', ++fmt;
else if (x.qual == 'l' && *fmt == 'l')
x.qual = 'q', ++fmt;
}
{ /* do the conversion */
char ac[_MAX_SIG_DIG + _MAX_EXP_DIG + 16];
if (_Putfld(&x, &ap, *fmt++, ac) || _Puttxt(&x, ac) < 0)
return (EOF);
}
}
}
_STD_END
/*
* Copyright (c) 1992-2006 by P.J. Plauger. ALL RIGHTS RESERVED.
* Consult your license regarding permissions and restrictions.
V5.00:1296 */
__SRCVERSION("xprintf.c $Rev: 153052 $");