forked from KolibriOS/kolibrios
775 lines
16 KiB
C
775 lines
16 KiB
C
|
/*
|
||
|
* vsprintf - print formatted output without ellipsis on an array
|
||
|
*/
|
||
|
/* $Header$ */
|
||
|
|
||
|
//#include "stdio.h"
|
||
|
//#include <stdarg.h>
|
||
|
|
||
|
typedef unsigned size_t;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
char *_ptr;
|
||
|
unsigned _count;
|
||
|
}__str;
|
||
|
|
||
|
|
||
|
#define va_start(v,l) __builtin_va_start(v,l)
|
||
|
#define va_end(v) __builtin_va_end(v)
|
||
|
#define va_arg(v,l) __builtin_va_arg(v,l)
|
||
|
#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L
|
||
|
#define va_copy(d,s) __builtin_va_copy(d,s)
|
||
|
#endif
|
||
|
#define __va_copy(d,s) __builtin_va_copy(d,s)
|
||
|
|
||
|
typedef __builtin_va_list __gnuc_va_list;
|
||
|
typedef __gnuc_va_list va_list;
|
||
|
|
||
|
#define arg(x) va_arg (ap, u32)
|
||
|
|
||
|
#define io_testflag(p,x) ((p)->_flags & (x))
|
||
|
|
||
|
char *_i_compute(unsigned long val, int base, char *s, int nrdigits);
|
||
|
char *_f_print(va_list *ap, int flags, char *s, char c, int precision);
|
||
|
void __cleanup(void);
|
||
|
|
||
|
|
||
|
void *calloc( size_t num, size_t size );
|
||
|
int memcmp(const void *s1, const void *s2, size_t n);
|
||
|
void * memcpy(void * _dest, const void *_src, size_t _n);
|
||
|
char * strcpy(char *to, const char *from);
|
||
|
char * strcat(char *s, const char *append);
|
||
|
int strcmp(const char *s1, const char *s2);
|
||
|
size_t strlen(const char *str);
|
||
|
char * strdup(const char *_s);
|
||
|
char * strchr(const char *s, int c);
|
||
|
|
||
|
|
||
|
#define FL_LJUST 0x0001 /* left-justify field */
|
||
|
#define FL_SIGN 0x0002 /* sign in signed conversions */
|
||
|
#define FL_SPACE 0x0004 /* space in signed conversions */
|
||
|
#define FL_ALT 0x0008 /* alternate form */
|
||
|
#define FL_ZEROFILL 0x0010 /* fill with zero's */
|
||
|
#define FL_SHORT 0x0020 /* optional h */
|
||
|
#define FL_LONG 0x0040 /* optional l */
|
||
|
#define FL_LONGDOUBLE 0x0080 /* optional L */
|
||
|
#define FL_WIDTHSPEC 0x0100 /* field width is specified */
|
||
|
#define FL_PRECSPEC 0x0200 /* precision is specified */
|
||
|
#define FL_SIGNEDCONV 0x0400 /* may contain a sign */
|
||
|
#define FL_NOASSIGN 0x0800 /* do not assign (in scanf) */
|
||
|
#define FL_NOMORE 0x1000 /* all flags collected */
|
||
|
|
||
|
#define _IOFBF 0x000
|
||
|
#define _IOREAD 0x001
|
||
|
#define _IOWRITE 0x002
|
||
|
#define _IONBF 0x004
|
||
|
#define _IOMYBUF 0x008
|
||
|
#define _IOEOF 0x010
|
||
|
#define _IOERR 0x020
|
||
|
#define _IOLBF 0x040
|
||
|
#define _IOREADING 0x080
|
||
|
#define _IOWRITING 0x100
|
||
|
#define _IOAPPEND 0x200
|
||
|
#define _IOFIFO 0x400
|
||
|
|
||
|
#define SGL_MAX 254 /* standard definition */
|
||
|
#define SGL_MIN 1 /* standard definition */
|
||
|
#define DBL_MAX 2046 /* standard definition */
|
||
|
#define DBL_MIN 1 /* standard definition */
|
||
|
#define EXT_MAX 16383 /* standard minimum */
|
||
|
#define EXT_MIN -16382 /* standard minimum */
|
||
|
#include <limits.h>
|
||
|
|
||
|
static char *cvt();
|
||
|
#define NDIGITS 128
|
||
|
|
||
|
unsigned char __dj_ctype_toupper[] = {
|
||
|
0x00,
|
||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||
|
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||
|
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||
|
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||
|
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||
|
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||
|
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||
|
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||
|
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||
|
0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||
|
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||
|
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||
|
0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||
|
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||
|
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||
|
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||
|
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||
|
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||
|
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||
|
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||
|
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||
|
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||
|
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||
|
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||
|
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||
|
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||
|
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||
|
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||
|
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
||
|
};
|
||
|
#define toupper(c) (__dj_ctype_toupper[(int)(c)+1])
|
||
|
|
||
|
int (toupper)(int c)
|
||
|
{
|
||
|
return toupper(c);
|
||
|
}
|
||
|
|
||
|
char *
|
||
|
_ecvt(value, ndigit, decpt, sign)
|
||
|
double value;
|
||
|
int ndigit, *decpt, *sign;
|
||
|
{
|
||
|
return cvt(value, ndigit, decpt, sign, 1);
|
||
|
}
|
||
|
|
||
|
char *
|
||
|
_fcvt(value, ndigit, decpt, sign)
|
||
|
double value;
|
||
|
int ndigit, *decpt, *sign;
|
||
|
{
|
||
|
return cvt(value, ndigit, decpt, sign, 0);
|
||
|
}
|
||
|
|
||
|
static struct powers_of_10 {
|
||
|
double pval;
|
||
|
double rpval;
|
||
|
int exp;
|
||
|
} p10[] = {
|
||
|
1.0e32, 1.0e-32, 32,
|
||
|
1.0e16, 1.0e-16, 16,
|
||
|
1.0e8, 1.0e-8, 8,
|
||
|
1.0e4, 1.0e-4, 4,
|
||
|
1.0e2, 1.0e-2, 2,
|
||
|
1.0e1, 1.0e-1, 1,
|
||
|
1.0e0, 1.0e0, 0
|
||
|
};
|
||
|
|
||
|
static char *
|
||
|
cvt(value, ndigit, decpt, sign, ecvtflag)
|
||
|
double value;
|
||
|
int ndigit, *decpt, *sign;
|
||
|
{
|
||
|
static char buf[NDIGITS+1];
|
||
|
register char *p = buf;
|
||
|
register char *pe;
|
||
|
|
||
|
if (ndigit < 0) ndigit = 0;
|
||
|
if (ndigit > NDIGITS) ndigit = NDIGITS;
|
||
|
pe = &buf[ndigit];
|
||
|
buf[0] = '\0';
|
||
|
|
||
|
*sign = 0;
|
||
|
if (value < 0) {
|
||
|
*sign = 1;
|
||
|
value = -value;
|
||
|
}
|
||
|
|
||
|
*decpt = 0;
|
||
|
if (value >= DBL_MAX) {
|
||
|
value = DBL_MAX;
|
||
|
}
|
||
|
if (value != 0.0) {
|
||
|
register struct powers_of_10 *pp = &p10[0];
|
||
|
|
||
|
if (value >= 10.0) do {
|
||
|
while (value >= pp->pval) {
|
||
|
value *= pp->rpval;
|
||
|
*decpt += pp->exp;
|
||
|
}
|
||
|
} while ((++pp)->exp > 0);
|
||
|
|
||
|
pp = &p10[0];
|
||
|
if (value < 1.0) do {
|
||
|
while (value * pp->pval < 10.0) {
|
||
|
value *= pp->pval;
|
||
|
*decpt -= pp->exp;
|
||
|
}
|
||
|
} while ((++pp)->exp > 0);
|
||
|
|
||
|
(*decpt)++; /* because now value in [1.0, 10.0) */
|
||
|
}
|
||
|
if (! ecvtflag) {
|
||
|
/* for fcvt() we need ndigit digits behind the dot */
|
||
|
pe += *decpt;
|
||
|
if (pe > &buf[NDIGITS]) pe = &buf[NDIGITS];
|
||
|
}
|
||
|
while (p <= pe) {
|
||
|
*p++ = (int)value + '0';
|
||
|
value = 10.0 * (value - (int)value);
|
||
|
}
|
||
|
if (pe >= buf) {
|
||
|
p = pe;
|
||
|
*p += 5; /* round of at the end */
|
||
|
while (*p > '9') {
|
||
|
*p = '0';
|
||
|
if (p > buf) ++*--p;
|
||
|
else {
|
||
|
*p = '1';
|
||
|
++*decpt;
|
||
|
if (! ecvtflag) {
|
||
|
/* maybe add another digit at the end,
|
||
|
because the point was shifted right
|
||
|
*/
|
||
|
if (pe > buf) *pe = '0';
|
||
|
pe++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
*pe = '\0';
|
||
|
}
|
||
|
return buf;
|
||
|
}
|
||
|
|
||
|
|
||
|
int _fp_hook = 1;
|
||
|
|
||
|
static char *
|
||
|
_pfloat(double r, register char *s, int n, int flags)
|
||
|
{
|
||
|
register char *s1;
|
||
|
int sign, dp;
|
||
|
register int i;
|
||
|
|
||
|
s1 = _fcvt(r, n, &dp, &sign);
|
||
|
if (sign)
|
||
|
*s++ = '-';
|
||
|
else if (flags & FL_SIGN)
|
||
|
*s++ = '+';
|
||
|
else if (flags & FL_SPACE)
|
||
|
*s++ = ' ';
|
||
|
|
||
|
if (dp<=0)
|
||
|
*s++ = '0';
|
||
|
for (i=dp; i>0; i--)
|
||
|
if (*s1) *s++ = *s1++;
|
||
|
else *s++ = '0';
|
||
|
if (((i=n) > 0) || (flags & FL_ALT))
|
||
|
*s++ = '.';
|
||
|
while (++dp <= 0) {
|
||
|
if (--i<0)
|
||
|
break;
|
||
|
*s++ = '0';
|
||
|
}
|
||
|
while (--i >= 0)
|
||
|
if (*s1) *s++ = *s1++;
|
||
|
else *s++ = '0';
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
static char *
|
||
|
_pscien(double r, register char *s, int n, int flags)
|
||
|
{
|
||
|
int sign, dp;
|
||
|
register char *s1;
|
||
|
|
||
|
s1 = _ecvt(r, n + 1, &dp, &sign);
|
||
|
if (sign)
|
||
|
*s++ = '-';
|
||
|
else if (flags & FL_SIGN)
|
||
|
*s++ = '+';
|
||
|
else if (flags & FL_SPACE)
|
||
|
*s++ = ' ';
|
||
|
|
||
|
*s++ = *s1++;
|
||
|
if ((n > 0) || (flags & FL_ALT))
|
||
|
*s++ = '.';
|
||
|
while (--n >= 0)
|
||
|
if (*s1) *s++ = *s1++;
|
||
|
else *s++ = '0';
|
||
|
*s++ = 'e';
|
||
|
if ( r != 0 ) --dp ;
|
||
|
if ( dp<0 ) {
|
||
|
*s++ = '-' ; dp= -dp ;
|
||
|
} else {
|
||
|
*s++ = '+' ;
|
||
|
}
|
||
|
if (dp >= 100) {
|
||
|
*s++ = '0' + (dp / 100);
|
||
|
dp %= 100;
|
||
|
}
|
||
|
*s++ = '0' + (dp/10);
|
||
|
*s++ = '0' + (dp%10);
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
#define NDIGINEXP(exp) (((exp) >= 100 || (exp) <= -100) ? 3 : 2)
|
||
|
#define LOW_EXP -4
|
||
|
#define USE_EXP(exp, ndigits) (((exp) < LOW_EXP + 1) || (exp >= ndigits + 1))
|
||
|
|
||
|
static char *
|
||
|
_gcvt(double value, int ndigit, char *s, int flags)
|
||
|
{
|
||
|
int sign, dp;
|
||
|
register char *s1, *s2;
|
||
|
register int i;
|
||
|
register int nndigit = ndigit;
|
||
|
|
||
|
s1 = _ecvt(value, ndigit, &dp, &sign);
|
||
|
s2 = s;
|
||
|
if (sign) *s2++ = '-';
|
||
|
else if (flags & FL_SIGN)
|
||
|
*s2++ = '+';
|
||
|
else if (flags & FL_SPACE)
|
||
|
*s2++ = ' ';
|
||
|
|
||
|
if (!(flags & FL_ALT))
|
||
|
for (i = nndigit - 1; i > 0 && s1[i] == '0'; i--)
|
||
|
nndigit--;
|
||
|
|
||
|
if (USE_EXP(dp,ndigit)) {
|
||
|
/* Use E format */
|
||
|
dp--;
|
||
|
*s2++ = *s1++;
|
||
|
if ((nndigit > 1) || (flags & FL_ALT)) *s2++ = '.';
|
||
|
while (--nndigit > 0) *s2++ = *s1++;
|
||
|
*s2++ = 'e';
|
||
|
if (dp < 0) {
|
||
|
*s2++ = '-';
|
||
|
dp = -dp;
|
||
|
}
|
||
|
else *s2++ = '+';
|
||
|
s2 += NDIGINEXP(dp);
|
||
|
*s2 = 0;
|
||
|
for (i = NDIGINEXP(dp); i > 0; i--) {
|
||
|
*--s2 = dp % 10 + '0';
|
||
|
dp /= 10;
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
/* Use f format */
|
||
|
if (dp <= 0) {
|
||
|
if (*s1 != '0') {
|
||
|
/* otherwise the whole number is 0 */
|
||
|
*s2++ = '0';
|
||
|
*s2++ = '.';
|
||
|
}
|
||
|
while (dp < 0) {
|
||
|
dp++;
|
||
|
*s2++ = '0';
|
||
|
}
|
||
|
}
|
||
|
for (i = 1; i <= nndigit; i++) {
|
||
|
*s2++ = *s1++;
|
||
|
if (i == dp) *s2++ = '.';
|
||
|
}
|
||
|
if (i <= dp) {
|
||
|
while (i++ <= dp) *s2++ = '0';
|
||
|
*s2++ = '.';
|
||
|
}
|
||
|
if ((s2[-1]=='.') && !(flags & FL_ALT)) s2--;
|
||
|
*s2 = '\0';
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
char *
|
||
|
_f_print(va_list *ap, int flags, char *s, char c, int precision)
|
||
|
{
|
||
|
register char *old_s = s;
|
||
|
double ld_val;
|
||
|
|
||
|
// if (flags & FL_LONGDOUBLE) ld_val = va_arg(*ap, double);
|
||
|
// else
|
||
|
ld_val = (double) va_arg(*ap, double);
|
||
|
|
||
|
switch(c) {
|
||
|
case 'f':
|
||
|
s = _pfloat(ld_val, s, precision, flags);
|
||
|
break;
|
||
|
case 'e':
|
||
|
case 'E':
|
||
|
s = _pscien(ld_val, s, precision , flags);
|
||
|
break;
|
||
|
case 'g':
|
||
|
case 'G':
|
||
|
s = _gcvt(ld_val, precision, s, flags);
|
||
|
s += strlen(s);
|
||
|
break;
|
||
|
}
|
||
|
if ( c == 'E' || c == 'G') {
|
||
|
while (*old_s && *old_s != 'e') old_s++;
|
||
|
if (*old_s == 'e') *old_s = 'E';
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
//#endif /* NOFLOAT */
|
||
|
/* $Header$ */
|
||
|
|
||
|
//#include <stdlib.h>
|
||
|
//#include "../ansi/ext_fmt.h"
|
||
|
|
||
|
//void _str_ext_cvt(const char *s, char **ss, struct EXTEND *e);
|
||
|
//double _ext_dbl_cvt(struct EXTEND *e);
|
||
|
|
||
|
//double
|
||
|
//strtod(const char *p, char **pp)
|
||
|
//{
|
||
|
// struct EXTEND e;
|
||
|
|
||
|
// _str_ext_cvt(p, pp, &e);
|
||
|
// return _ext_dbl_cvt(&e);
|
||
|
//}
|
||
|
|
||
|
#define BUFSIZ 4096
|
||
|
#define NULL ((void *)0)
|
||
|
#define EOF (-1)
|
||
|
|
||
|
|
||
|
/* gnum() is used to get the width and precision fields of a format. */
|
||
|
static const char *
|
||
|
gnum(register const char *f, int *ip, va_list *app)
|
||
|
{
|
||
|
register int i, c;
|
||
|
|
||
|
if (*f == '*') {
|
||
|
*ip = va_arg((*app), int);
|
||
|
f++;
|
||
|
} else {
|
||
|
i = 0;
|
||
|
while ((c = *f - '0') >= 0 && c <= 9) {
|
||
|
i = i*10 + c;
|
||
|
f++;
|
||
|
}
|
||
|
*ip = i;
|
||
|
}
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
#if _EM_WSIZE == _EM_PSIZE
|
||
|
#define set_pointer(flags) /* nothing */
|
||
|
#elif _EM_LSIZE == _EM_PSIZE
|
||
|
#define set_pointer(flags) (flags |= FL_LONG)
|
||
|
#else
|
||
|
#error garbage pointer size
|
||
|
#define set_pointer(flags) /* compilation might continue */
|
||
|
#endif
|
||
|
|
||
|
/* print an ordinal number */
|
||
|
static char *
|
||
|
o_print(va_list *ap, int flags, char *s, char c, int precision, int is_signed)
|
||
|
{
|
||
|
long signed_val;
|
||
|
unsigned long unsigned_val;
|
||
|
char *old_s = s;
|
||
|
int base;
|
||
|
|
||
|
switch (flags & (FL_SHORT | FL_LONG)) {
|
||
|
case FL_SHORT:
|
||
|
if (is_signed) {
|
||
|
signed_val = (short) va_arg(*ap, int);
|
||
|
} else {
|
||
|
unsigned_val = (unsigned short) va_arg(*ap, unsigned);
|
||
|
}
|
||
|
break;
|
||
|
case FL_LONG:
|
||
|
if (is_signed) {
|
||
|
signed_val = va_arg(*ap, long);
|
||
|
} else {
|
||
|
unsigned_val = va_arg(*ap, unsigned long);
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
if (is_signed) {
|
||
|
signed_val = va_arg(*ap, int);
|
||
|
} else {
|
||
|
unsigned_val = va_arg(*ap, unsigned int);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (is_signed) {
|
||
|
if (signed_val < 0) {
|
||
|
*s++ = '-';
|
||
|
signed_val = -signed_val;
|
||
|
} else if (flags & FL_SIGN) *s++ = '+';
|
||
|
else if (flags & FL_SPACE) *s++ = ' ';
|
||
|
unsigned_val = signed_val;
|
||
|
}
|
||
|
if ((flags & FL_ALT) && (c == 'o')) *s++ = '0';
|
||
|
if (!unsigned_val && c != 'p') {
|
||
|
if (!precision)
|
||
|
return s;
|
||
|
} else if (((flags & FL_ALT) && (c == 'x' || c == 'X'))
|
||
|
|| c == 'p') {
|
||
|
*s++ = '0';
|
||
|
*s++ = (c == 'X' ? 'X' : 'x');
|
||
|
}
|
||
|
|
||
|
switch (c) {
|
||
|
case 'b': base = 2; break;
|
||
|
case 'o': base = 8; break;
|
||
|
case 'd':
|
||
|
case 'i':
|
||
|
case 'u': base = 10; break;
|
||
|
case 'x':
|
||
|
case 'X':
|
||
|
case 'p': base = 16; break;
|
||
|
}
|
||
|
|
||
|
s = _i_compute(unsigned_val, base, s, precision);
|
||
|
|
||
|
if (c == 'X')
|
||
|
while (old_s != s) {
|
||
|
*old_s = toupper(*old_s);
|
||
|
old_s++;
|
||
|
}
|
||
|
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
|
||
|
#define putc(c, p) (--(p)->_count >= 0 ? (int) (*(p)->_ptr++ = (c)) : EOF)
|
||
|
|
||
|
int
|
||
|
_doprnt(register const char *fmt, va_list ap, __str *stream)
|
||
|
{
|
||
|
register char *s;
|
||
|
register int j;
|
||
|
int i, c, width, precision, zfill, flags, between_fill;
|
||
|
int nrchars=0;
|
||
|
const char *oldfmt;
|
||
|
char *s1, buf[512];
|
||
|
|
||
|
while (c = *fmt++)
|
||
|
{
|
||
|
if (c != '%')
|
||
|
{
|
||
|
if (c == '\n')
|
||
|
{
|
||
|
if (putc('\r', stream) == EOF)
|
||
|
return nrchars ? -nrchars : -1;
|
||
|
nrchars++;
|
||
|
}
|
||
|
if (putc(c, stream) == EOF)
|
||
|
return nrchars ? -nrchars : -1;
|
||
|
nrchars++;
|
||
|
continue;
|
||
|
}
|
||
|
flags = 0;
|
||
|
do {
|
||
|
switch(*fmt) {
|
||
|
case '-': flags |= FL_LJUST; break;
|
||
|
case '+': flags |= FL_SIGN; break;
|
||
|
case ' ': flags |= FL_SPACE; break;
|
||
|
case '#': flags |= FL_ALT; break;
|
||
|
case '0': flags |= FL_ZEROFILL; break;
|
||
|
default: flags |= FL_NOMORE; continue;
|
||
|
}
|
||
|
fmt++;
|
||
|
} while(!(flags & FL_NOMORE));
|
||
|
|
||
|
oldfmt = fmt;
|
||
|
fmt = gnum(fmt, &width, &ap);
|
||
|
if (fmt != oldfmt) flags |= FL_WIDTHSPEC;
|
||
|
|
||
|
if (*fmt == '.') {
|
||
|
fmt++; oldfmt = fmt;
|
||
|
fmt = gnum(fmt, &precision, &ap);
|
||
|
if (precision >= 0) flags |= FL_PRECSPEC;
|
||
|
}
|
||
|
|
||
|
if ((flags & FL_WIDTHSPEC) && width < 0) {
|
||
|
width = -width;
|
||
|
flags |= FL_LJUST;
|
||
|
}
|
||
|
if (!(flags & FL_WIDTHSPEC)) width = 0;
|
||
|
|
||
|
if (flags & FL_SIGN) flags &= ~FL_SPACE;
|
||
|
|
||
|
if (flags & FL_LJUST) flags &= ~FL_ZEROFILL;
|
||
|
|
||
|
|
||
|
s = s1 = buf;
|
||
|
|
||
|
switch (*fmt) {
|
||
|
case 'h': flags |= FL_SHORT; fmt++; break;
|
||
|
case 'l': flags |= FL_LONG; fmt++; break;
|
||
|
case 'L': flags |= FL_LONGDOUBLE; fmt++; break;
|
||
|
}
|
||
|
|
||
|
switch (c = *fmt++) {
|
||
|
default:
|
||
|
if (c == '\n') {
|
||
|
if (putc('\r', stream) == EOF)
|
||
|
return nrchars ? -nrchars : -1;
|
||
|
nrchars++;
|
||
|
}
|
||
|
if (putc(c, stream) == EOF)
|
||
|
return nrchars ? -nrchars : -1;
|
||
|
nrchars++;
|
||
|
continue;
|
||
|
case 'n':
|
||
|
if (flags & FL_SHORT)
|
||
|
*va_arg(ap, short *) = (short) nrchars;
|
||
|
else if (flags & FL_LONG)
|
||
|
*va_arg(ap, long *) = (long) nrchars;
|
||
|
else
|
||
|
*va_arg(ap, int *) = (int) nrchars;
|
||
|
continue;
|
||
|
case 's':
|
||
|
s1 = va_arg(ap, char *);
|
||
|
if (s1 == NULL)
|
||
|
s1 = "(null)";
|
||
|
s = s1;
|
||
|
while (precision || !(flags & FL_PRECSPEC)) {
|
||
|
if (*s == '\0')
|
||
|
break;
|
||
|
s++;
|
||
|
precision--;
|
||
|
}
|
||
|
break;
|
||
|
case 'p':
|
||
|
set_pointer(flags);
|
||
|
/* fallthrough */
|
||
|
case 'b':
|
||
|
case 'o':
|
||
|
case 'u':
|
||
|
case 'x':
|
||
|
case 'X':
|
||
|
if (!(flags & FL_PRECSPEC)) precision = 1;
|
||
|
else if (c != 'p') flags &= ~FL_ZEROFILL;
|
||
|
s = o_print(&ap, flags, s, c, precision, 0);
|
||
|
break;
|
||
|
case 'd':
|
||
|
case 'i':
|
||
|
flags |= FL_SIGNEDCONV;
|
||
|
if (!(flags & FL_PRECSPEC)) precision = 1;
|
||
|
else flags &= ~FL_ZEROFILL;
|
||
|
s = o_print(&ap, flags, s, c, precision, 1);
|
||
|
break;
|
||
|
case 'c':
|
||
|
*s++ = va_arg(ap, int);
|
||
|
break;
|
||
|
|
||
|
case 'G':
|
||
|
case 'g':
|
||
|
if ((flags & FL_PRECSPEC) && (precision == 0))
|
||
|
precision = 1;
|
||
|
case 'f':
|
||
|
case 'E':
|
||
|
case 'e':
|
||
|
if (!(flags & FL_PRECSPEC))
|
||
|
precision = 6;
|
||
|
|
||
|
if (precision >= sizeof(buf))
|
||
|
precision = sizeof(buf) - 1;
|
||
|
|
||
|
flags |= FL_SIGNEDCONV;
|
||
|
s = _f_print(&ap, flags, s, c, precision);
|
||
|
break;
|
||
|
case 'r':
|
||
|
ap = va_arg(ap, va_list);
|
||
|
fmt = va_arg(ap, char *);
|
||
|
continue;
|
||
|
}
|
||
|
zfill = ' ';
|
||
|
if (flags & FL_ZEROFILL) zfill = '0';
|
||
|
j = s - s1;
|
||
|
|
||
|
/* between_fill is true under the following conditions:
|
||
|
* 1- the fill character is '0'
|
||
|
* and
|
||
|
* 2a- the number is of the form 0x... or 0X...
|
||
|
* or
|
||
|
* 2b- the number contains a sign or space
|
||
|
*/
|
||
|
between_fill = 0;
|
||
|
if ((flags & FL_ZEROFILL)
|
||
|
&& (((c == 'x' || c == 'X') && (flags & FL_ALT) && j > 1)
|
||
|
|| (c == 'p')
|
||
|
|| ((flags & FL_SIGNEDCONV)
|
||
|
&& ( *s1 == '+' || *s1 == '-' || *s1 == ' '))))
|
||
|
between_fill++;
|
||
|
|
||
|
if ((i = width - j) > 0)
|
||
|
if (!(flags & FL_LJUST)) { /* right justify */
|
||
|
nrchars += i;
|
||
|
if (between_fill) {
|
||
|
if (flags & FL_SIGNEDCONV) {
|
||
|
j--; nrchars++;
|
||
|
if (putc(*s1++, stream) == EOF)
|
||
|
return nrchars ? -nrchars : -1;
|
||
|
} else {
|
||
|
j -= 2; nrchars += 2;
|
||
|
if ((putc(*s1++, stream) == EOF)
|
||
|
|| (putc(*s1++, stream) == EOF))
|
||
|
return nrchars ? -nrchars : -1;
|
||
|
}
|
||
|
}
|
||
|
do {
|
||
|
if (putc(zfill, stream) == EOF)
|
||
|
return nrchars ? -nrchars : -1;
|
||
|
} while (--i);
|
||
|
}
|
||
|
|
||
|
nrchars += j;
|
||
|
while (--j >= 0) {
|
||
|
if (putc(*s1++, stream) == EOF)
|
||
|
return nrchars ? -nrchars : -1;
|
||
|
}
|
||
|
|
||
|
if (i > 0) nrchars += i;
|
||
|
while (--i >= 0)
|
||
|
if (putc(zfill, stream) == EOF)
|
||
|
return nrchars ? -nrchars : -1;
|
||
|
}
|
||
|
return nrchars;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
vsnprintf(char *s, size_t n, const char *format, va_list arg)
|
||
|
{
|
||
|
int retval;
|
||
|
__str tmp_stream;
|
||
|
|
||
|
//tmp_stream._buf = (unsigned char *) s;
|
||
|
tmp_stream._ptr = (unsigned char *) s;
|
||
|
tmp_stream._count = n-1;
|
||
|
|
||
|
retval = _doprnt(format, arg, &tmp_stream);
|
||
|
tmp_stream._count = 1;
|
||
|
putc('\0',&tmp_stream);
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
vsprintf(char *s, const char *format, va_list arg)
|
||
|
{
|
||
|
return vsnprintf(s, INT_MAX, format, arg);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|