fixed more bugs in printf.c/printf.h
This commit is contained in:
parent
fde2e1a3b0
commit
99ac89fc57
@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
Copyright 2006-2012 Chung, Hyung-Hwan.
|
||||||
|
This file is part of QSE.
|
||||||
|
|
||||||
|
QSE is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
QSE 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <qse/cmn/chr.h>
|
#include <qse/cmn/chr.h>
|
||||||
#include <qse/cmn/str.h>
|
#include <qse/cmn/str.h>
|
||||||
@ -13,13 +33,16 @@
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
/* integer */
|
||||||
LF_C = (1 << 0),
|
LF_C = (1 << 0),
|
||||||
LF_H = (1 << 1),
|
LF_H = (1 << 1),
|
||||||
LF_J = (1 << 2),
|
LF_J = (1 << 2),
|
||||||
LF_L = (1 << 3),
|
LF_L = (1 << 3),
|
||||||
LF_Q = (1 << 4),
|
LF_Q = (1 << 4),
|
||||||
LF_T = (1 << 5),
|
LF_Z = (1 << 5),
|
||||||
LF_Z = (1 << 6)
|
|
||||||
|
/* long double */
|
||||||
|
LF_LD = (1 << 6)
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
@ -47,7 +70,7 @@ static struct
|
|||||||
{ LF_Q, 0 }, /* q */
|
{ LF_Q, 0 }, /* q */
|
||||||
{ 0, 0 }, /* r */
|
{ 0, 0 }, /* r */
|
||||||
{ 0, 0 }, /* s */
|
{ 0, 0 }, /* s */
|
||||||
{ LF_T, 0 }, /* t */
|
{ 0, 0 }, /* t */
|
||||||
{ 0, 0 }, /* u */
|
{ 0, 0 }, /* u */
|
||||||
{ 0, 0 }, /* v */
|
{ 0, 0 }, /* v */
|
||||||
{ 0, 0 }, /* w */
|
{ 0, 0 }, /* w */
|
||||||
@ -65,7 +88,11 @@ enum
|
|||||||
FLAGC_SPACE = (1 << 3),
|
FLAGC_SPACE = (1 << 3),
|
||||||
FLAGC_LEFTADJ = (1 << 4),
|
FLAGC_LEFTADJ = (1 << 4),
|
||||||
FLAGC_ZEROPAD = (1 << 5),
|
FLAGC_ZEROPAD = (1 << 5),
|
||||||
FLAGC_WIDTH = (1 << 6)
|
FLAGC_WIDTH = (1 << 6),
|
||||||
|
FLAGC_PRECISION = (1 << 7),
|
||||||
|
FLAGC_STAR1 = (1 << 8),
|
||||||
|
FLAGC_STAR2 = (1 << 9),
|
||||||
|
FLAGC_LENMOD = (1 << 10) /* length modifier */
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <stdio.h> /* TODO: remove dependency on this */
|
#include <stdio.h> /* TODO: remove dependency on this */
|
||||||
|
@ -1,4 +1,29 @@
|
|||||||
/*-
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
Copyright 2006-2012 Chung, Hyung-Hwan.
|
||||||
|
This file is part of QSE.
|
||||||
|
|
||||||
|
QSE is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
QSE 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains a formatted output routine derived from kvprintf()
|
||||||
|
* of FreeBSD. It has been heavily modified and bug-fixed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
* Copyright (c) 1986, 1988, 1991, 1993
|
* Copyright (c) 1986, 1988, 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
* (c) UNIX System Laboratories, Inc.
|
* (c) UNIX System Laboratories, Inc.
|
||||||
@ -31,14 +56,8 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define NBBY 8 /* number of bits in a byte */
|
|
||||||
|
|
||||||
/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
|
|
||||||
#define MAXNBUF (QSE_SIZEOF(qse_intmax_t) * NBBY + 1)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
|
* Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
|
||||||
* order; return an optional length and a pointer to the last character
|
* order; return an optional length and a pointer to the last character
|
||||||
@ -80,24 +99,17 @@ int xprintf (char_t const *fmt, void (*put_char)(char_t, void*), void (*put_ocha
|
|||||||
{
|
{
|
||||||
char_t nbuf[MAXNBUF];
|
char_t nbuf[MAXNBUF];
|
||||||
const char_t* p, * percent;
|
const char_t* p, * percent;
|
||||||
|
int n, base, tmp, width, neg, sign, precision, upper;
|
||||||
uchar_t ch;
|
uchar_t ch;
|
||||||
int n;
|
char_t ach, padc, * sp;
|
||||||
qse_uintmax_t num;
|
ochar_t oach, opadc, * osp;
|
||||||
int base, tmp, width, neg, sign;
|
int lm_flag, lm_dflag, flagc, numlen;
|
||||||
int precision, upper;
|
qse_uintmax_t num = 0;
|
||||||
char_t padc, * sp;
|
|
||||||
ochar_t opadc, * osp;
|
|
||||||
int stop = 0, retval = 0;
|
int stop = 0, retval = 0;
|
||||||
int lm_flag, lm_dflag, flagc;
|
char_t fltbuf[100];
|
||||||
int numlen;
|
|
||||||
|
|
||||||
num = 0;
|
|
||||||
|
|
||||||
/*if (fmt == QSE_NULL) fmt = T("(fmt null)\n");*/
|
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
|
||||||
while ((ch = (uchar_t)*fmt++) != T('%') || stop)
|
while ((ch = (uchar_t)*fmt++) != T('%') || stop)
|
||||||
{
|
{
|
||||||
if (ch == T('\0')) return retval;
|
if (ch == T('\0')) return retval;
|
||||||
@ -115,31 +127,33 @@ reswitch:
|
|||||||
switch (ch = (uchar_t)*fmt++)
|
switch (ch = (uchar_t)*fmt++)
|
||||||
{
|
{
|
||||||
case T('%'): /* %% */
|
case T('%'): /* %% */
|
||||||
PUT_CHAR(ch);
|
ach = ch;
|
||||||
|
goto print_lowercase_c;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* flag characters */
|
/* flag characters */
|
||||||
case T('.'):
|
case T('.'):
|
||||||
|
if (flagc & FLAGC_DOT) goto invalid_format;
|
||||||
flagc |= FLAGC_DOT;
|
flagc |= FLAGC_DOT;
|
||||||
goto reswitch;
|
goto reswitch;
|
||||||
|
|
||||||
case T('#'):
|
case T('#'):
|
||||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT)) goto invalid_format;
|
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||||
flagc |= FLAGC_SHARP;
|
flagc |= FLAGC_SHARP;
|
||||||
goto reswitch;
|
goto reswitch;
|
||||||
|
|
||||||
case T(' '):
|
case T(' '):
|
||||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT)) goto invalid_format;
|
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||||
flagc |= FLAGC_SPACE;
|
flagc |= FLAGC_SPACE;
|
||||||
goto reswitch;
|
goto reswitch;
|
||||||
|
|
||||||
case T('+'): /* place sign for signed conversion */
|
case T('+'): /* place sign for signed conversion */
|
||||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT)) goto invalid_format;
|
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||||
flagc |= FLAGC_SIGN;
|
flagc |= FLAGC_SIGN;
|
||||||
goto reswitch;
|
goto reswitch;
|
||||||
|
|
||||||
case T('-'): /* left adjusted */
|
case T('-'): /* left adjusted */
|
||||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT)) goto invalid_format;
|
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||||
if (flagc & FLAGC_DOT)
|
if (flagc & FLAGC_DOT)
|
||||||
{
|
{
|
||||||
goto invalid_format;
|
goto invalid_format;
|
||||||
@ -158,8 +172,25 @@ reswitch:
|
|||||||
goto reswitch;
|
goto reswitch;
|
||||||
|
|
||||||
case T('*'): /* take the length from the parameter */
|
case T('*'): /* take the length from the parameter */
|
||||||
if (!(flagc & FLAGC_DOT))
|
if (flagc & FLAGC_DOT)
|
||||||
{
|
{
|
||||||
|
if (flagc & (FLAGC_STAR2 | FLAGC_PRECISION)) goto invalid_format;
|
||||||
|
flagc |= FLAGC_STAR2;
|
||||||
|
|
||||||
|
precision = va_arg(ap, int);
|
||||||
|
if (precision < 0)
|
||||||
|
{
|
||||||
|
/* if precision is less than 0,
|
||||||
|
* treat it as if no .precision is specified */
|
||||||
|
flagc &= ~FLAGC_DOT;
|
||||||
|
precision = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (flagc & (FLAGC_STAR1 | FLAGC_WIDTH)) goto invalid_format;
|
||||||
|
flagc |= FLAGC_STAR1;
|
||||||
|
|
||||||
width = va_arg(ap, int);
|
width = va_arg(ap, int);
|
||||||
if (width < 0)
|
if (width < 0)
|
||||||
{
|
{
|
||||||
@ -172,22 +203,11 @@ reswitch:
|
|||||||
width = -width;
|
width = -width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
precision = va_arg(ap, int);
|
|
||||||
if (precision < 0)
|
|
||||||
{
|
|
||||||
/* if precision is less than 0,
|
|
||||||
* treat it as if no .precision is specified */
|
|
||||||
flagc &= ~FLAGC_DOT;
|
|
||||||
precision = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goto reswitch;
|
goto reswitch;
|
||||||
|
|
||||||
case T('0'): /* zero pad */
|
case T('0'): /* zero pad */
|
||||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT)) goto invalid_format;
|
if (flagc & FLAGC_LENMOD) goto invalid_format;
|
||||||
if (!(flagc & FLAGC_LEFTADJ))
|
if (!(flagc & (FLAGC_DOT | FLAGC_LEFTADJ)))
|
||||||
{
|
{
|
||||||
padc = T('0');
|
padc = T('0');
|
||||||
opadc = OT('0');
|
opadc = OT('0');
|
||||||
@ -204,9 +224,15 @@ reswitch:
|
|||||||
ch = *fmt;
|
ch = *fmt;
|
||||||
if (ch < T('0') || ch > T('9')) break;
|
if (ch < T('0') || ch > T('9')) break;
|
||||||
}
|
}
|
||||||
if (flagc & FLAGC_DOT) precision = n;
|
if (flagc & FLAGC_DOT)
|
||||||
|
{
|
||||||
|
if (flagc & FLAGC_STAR2) goto invalid_format;
|
||||||
|
precision = n;
|
||||||
|
flagc |= FLAGC_PRECISION;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (flagc & FLAGC_STAR1) goto invalid_format;
|
||||||
width = n;
|
width = n;
|
||||||
flagc |= FLAGC_WIDTH;
|
flagc |= FLAGC_WIDTH;
|
||||||
}
|
}
|
||||||
@ -218,15 +244,16 @@ reswitch:
|
|||||||
case T('q'): /* long long int */
|
case T('q'): /* long long int */
|
||||||
case T('j'): /* uintmax_t */
|
case T('j'): /* uintmax_t */
|
||||||
case T('z'): /* size_t */
|
case T('z'): /* size_t */
|
||||||
|
#if 0
|
||||||
case T('t'): /* ptrdiff_t */
|
case T('t'): /* ptrdiff_t */
|
||||||
|
#endif
|
||||||
|
if (lm_flag & LF_LD) goto invalid_format;
|
||||||
|
|
||||||
|
flagc |= FLAGC_LENMOD;
|
||||||
if (lm_dflag)
|
if (lm_dflag)
|
||||||
{
|
{
|
||||||
/* error */
|
/* error */
|
||||||
PUT_CHAR (fmt[-4]);
|
goto invalid_format;
|
||||||
PUT_CHAR (fmt[-3]);
|
|
||||||
PUT_CHAR (fmt[-2]);
|
|
||||||
PUT_CHAR (fmt[-1]);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else if (lm_flag)
|
else if (lm_flag)
|
||||||
{
|
{
|
||||||
@ -240,10 +267,7 @@ reswitch:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* error */
|
/* error */
|
||||||
PUT_CHAR (fmt[-3]);
|
goto invalid_format;
|
||||||
PUT_CHAR (fmt[-2]);
|
|
||||||
PUT_CHAR (fmt[-1]);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -252,6 +276,16 @@ reswitch:
|
|||||||
goto reswitch;
|
goto reswitch;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T('L'): /* long double */
|
||||||
|
if (flagc & FLAGC_LENMOD)
|
||||||
|
{
|
||||||
|
/* conflict integral length modifier */
|
||||||
|
goto invalid_format;
|
||||||
|
}
|
||||||
|
flagc |= FLAGC_LENMOD;
|
||||||
|
lm_flag |= LF_LD;
|
||||||
|
goto reswitch;
|
||||||
/* end of length modifiers */
|
/* end of length modifiers */
|
||||||
|
|
||||||
case T('n'):
|
case T('n'):
|
||||||
@ -277,6 +311,9 @@ reswitch:
|
|||||||
/* signed integer conversions */
|
/* signed integer conversions */
|
||||||
case T('d'):
|
case T('d'):
|
||||||
case T('i'): /* signed conversion */
|
case T('i'): /* signed conversion */
|
||||||
|
#if defined(NO_MERCY)
|
||||||
|
if (lm_flag & LF_LD) goto invalid_format;
|
||||||
|
#endif
|
||||||
base = 10;
|
base = 10;
|
||||||
sign = 1;
|
sign = 1;
|
||||||
goto handle_sign;
|
goto handle_sign;
|
||||||
@ -284,19 +321,31 @@ reswitch:
|
|||||||
|
|
||||||
/* unsigned integer conversions */
|
/* unsigned integer conversions */
|
||||||
case T('o'):
|
case T('o'):
|
||||||
|
#if defined(NO_MERCY)
|
||||||
|
if (lm_flag & LF_LD) goto invalid_format;
|
||||||
|
#endif
|
||||||
base = 8;
|
base = 8;
|
||||||
goto handle_nosign;
|
goto handle_nosign;
|
||||||
case T('u'):
|
case T('u'):
|
||||||
|
#if defined(NO_MERCY)
|
||||||
|
if (lm_flag & LF_LD) goto invalid_format;
|
||||||
|
#endif
|
||||||
base = 10;
|
base = 10;
|
||||||
goto handle_nosign;
|
goto handle_nosign;
|
||||||
case T('X'):
|
case T('X'):
|
||||||
upper = 1;
|
upper = 1;
|
||||||
case T('x'):
|
case T('x'):
|
||||||
|
#if defined(NO_MERCY)
|
||||||
|
if (lm_flag & LF_LD) goto invalid_format;
|
||||||
|
#endif
|
||||||
base = 16;
|
base = 16;
|
||||||
goto handle_nosign;
|
goto handle_nosign;
|
||||||
/* end of unsigned integer conversions */
|
/* end of unsigned integer conversions */
|
||||||
|
|
||||||
case T('p'): /* pointer */
|
case T('p'): /* pointer */
|
||||||
|
#if defined(NO_MERCY)
|
||||||
|
if (lm_flag & LF_LD) goto invalid_format;
|
||||||
|
#endif
|
||||||
base = 16;
|
base = 16;
|
||||||
|
|
||||||
if (width == 0) flagc |= FLAGC_SHARP;
|
if (width == 0) flagc |= FLAGC_SHARP;
|
||||||
@ -309,39 +358,59 @@ reswitch:
|
|||||||
if (((lm_flag & LF_H) && (QSE_SIZEOF(char_t) > QSE_SIZEOF(ochar_t))) ||
|
if (((lm_flag & LF_H) && (QSE_SIZEOF(char_t) > QSE_SIZEOF(ochar_t))) ||
|
||||||
((lm_flag & LF_L) && (QSE_SIZEOF(char_t) < QSE_SIZEOF(ochar_t)))) goto uppercase_c;
|
((lm_flag & LF_L) && (QSE_SIZEOF(char_t) < QSE_SIZEOF(ochar_t)))) goto uppercase_c;
|
||||||
lowercase_c:
|
lowercase_c:
|
||||||
if (QSE_SIZEOF(char_t) < QSE_SIZEOF(int))
|
ach = QSE_SIZEOF(char_t) < QSE_SIZEOF(int)? va_arg(ap, int): va_arg(ap, char_t);
|
||||||
PUT_CHAR(va_arg(ap, int));
|
|
||||||
else
|
print_lowercase_c:
|
||||||
PUT_CHAR(va_arg(ap, char_t));
|
/* precision 0 doesn't kill the letter */
|
||||||
|
width--;
|
||||||
|
if (!(flagc & FLAGC_LEFTADJ) && width > 0)
|
||||||
|
{
|
||||||
|
while (width--) PUT_CHAR (padc);
|
||||||
|
}
|
||||||
|
PUT_CHAR (ach);
|
||||||
|
if ((flagc & FLAGC_LEFTADJ) && width > 0)
|
||||||
|
{
|
||||||
|
while (width--) PUT_CHAR (padc);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T('C'):
|
case T('C'):
|
||||||
if (((lm_flag & LF_H) && (QSE_SIZEOF(char_t) < QSE_SIZEOF(ochar_t))) ||
|
if (((lm_flag & LF_H) && (QSE_SIZEOF(char_t) < QSE_SIZEOF(ochar_t))) ||
|
||||||
((lm_flag & LF_L) && (QSE_SIZEOF(char_t) > QSE_SIZEOF(ochar_t)))) goto lowercase_c;
|
((lm_flag & LF_L) && (QSE_SIZEOF(char_t) > QSE_SIZEOF(ochar_t)))) goto lowercase_c;
|
||||||
uppercase_c:
|
uppercase_c:
|
||||||
if (QSE_SIZEOF(ochar_t) < QSE_SIZEOF(int))
|
oach = QSE_SIZEOF(ochar_t) < QSE_SIZEOF(int)? va_arg(ap, int): va_arg(ap, ochar_t);
|
||||||
PUT_OCHAR(va_arg(ap, int));
|
|
||||||
else
|
/* precision 0 doesn't kill the letter */
|
||||||
PUT_OCHAR(va_arg(ap, ochar_t));
|
width--;
|
||||||
|
if (!(flagc & FLAGC_LEFTADJ) && width > 0)
|
||||||
|
{
|
||||||
|
while (width--) PUT_OCHAR (opadc);
|
||||||
|
}
|
||||||
|
PUT_OCHAR (oach);
|
||||||
|
if ((flagc & FLAGC_LEFTADJ) && width > 0)
|
||||||
|
{
|
||||||
|
while (width--) PUT_OCHAR (opadc);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T('s'):
|
case T('s'):
|
||||||
{
|
|
||||||
if (((lm_flag & LF_H) && (QSE_SIZEOF(char_t) > QSE_SIZEOF(ochar_t))) ||
|
if (((lm_flag & LF_H) && (QSE_SIZEOF(char_t) > QSE_SIZEOF(ochar_t))) ||
|
||||||
((lm_flag & LF_L) && (QSE_SIZEOF(char_t) < QSE_SIZEOF(ochar_t)))) goto uppercase_s;
|
((lm_flag & LF_L) && (QSE_SIZEOF(char_t) < QSE_SIZEOF(ochar_t)))) goto uppercase_s;
|
||||||
lowercase_s:
|
lowercase_s:
|
||||||
sp = va_arg (ap, char_t *);
|
sp = va_arg (ap, char_t *);
|
||||||
if (sp == QSE_NULL) p = T("(null)");
|
if (sp == QSE_NULL) p = T("(null)");
|
||||||
if (!(flagc & FLAGC_DOT))
|
|
||||||
|
print_lowercase_s:
|
||||||
|
if (flagc & FLAGC_DOT)
|
||||||
|
{
|
||||||
|
for (n = 0; n < precision && sp[n]; n++) continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
char_t* p = sp;
|
char_t* p = sp;
|
||||||
while (*p) p++;
|
while (*p) p++;
|
||||||
n = p - sp;
|
n = p - sp;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
for (n = 0; n < precision && sp[n]; n++) continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
width -= n;
|
width -= n;
|
||||||
|
|
||||||
@ -355,25 +424,23 @@ reswitch:
|
|||||||
while (width--) PUT_CHAR(padc);
|
while (width--) PUT_CHAR(padc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case T('S'):
|
case T('S'):
|
||||||
{
|
|
||||||
if (((lm_flag & LF_H) && (QSE_SIZEOF(char_t) < QSE_SIZEOF(ochar_t))) ||
|
if (((lm_flag & LF_H) && (QSE_SIZEOF(char_t) < QSE_SIZEOF(ochar_t))) ||
|
||||||
((lm_flag & LF_L) && (QSE_SIZEOF(char_t) > QSE_SIZEOF(ochar_t)))) goto lowercase_s;
|
((lm_flag & LF_L) && (QSE_SIZEOF(char_t) > QSE_SIZEOF(ochar_t)))) goto lowercase_s;
|
||||||
uppercase_s:
|
uppercase_s:
|
||||||
osp = va_arg (ap, ochar_t*);
|
osp = va_arg (ap, ochar_t*);
|
||||||
if (osp == QSE_NULL) osp = OT("(null)");
|
if (osp == QSE_NULL) osp = OT("(null)");
|
||||||
if (!(flagc & FLAGC_DOT))
|
if (flagc & FLAGC_DOT)
|
||||||
|
{
|
||||||
|
for (n = 0; n < precision && osp[n]; n++) continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ochar_t* p = osp;
|
ochar_t* p = osp;
|
||||||
while (*p) p++;
|
while (*p) p++;
|
||||||
n = p - osp;
|
n = p - osp;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
for (n = 0; n < precision && osp[n]; n++) continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
width -= n;
|
width -= n;
|
||||||
|
|
||||||
@ -387,12 +454,68 @@ reswitch:
|
|||||||
while (width--) PUT_OCHAR (opadc);
|
while (width--) PUT_OCHAR (opadc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T('e'):
|
||||||
|
case T('E'):
|
||||||
|
case T('f'):
|
||||||
|
case T('F'):
|
||||||
|
case T('g'):
|
||||||
|
case T('G'):
|
||||||
|
/*
|
||||||
|
case T('a'):
|
||||||
|
case T('A'):
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
qse_mchar_t tmpbuf[100];
|
||||||
|
qse_mchar_t tmpfmt[100];
|
||||||
|
const char_t* xx;
|
||||||
|
const qse_mchar_t* yy;
|
||||||
|
int q;
|
||||||
|
|
||||||
|
#if defined(NO_MERCY)
|
||||||
|
if (lm_flag & ~LF_LD) goto invalid_format;
|
||||||
|
#endif
|
||||||
|
for (xx = percent, q = 0; xx < fmt; xx++) tmpfmt[q++] = *xx;
|
||||||
|
tmpfmt[q] = QSE_MT('\0');
|
||||||
|
if (lm_flag & LF_LD)
|
||||||
|
snprintf (tmpbuf, QSE_SIZEOF(tmpbuf), tmpfmt, va_arg (ap, long double));
|
||||||
|
else
|
||||||
|
snprintf (tmpbuf, QSE_SIZEOF(tmpbuf), tmpfmt, va_arg (ap, double));
|
||||||
|
for (yy = tmpbuf, q = 0; *yy; ) fltbuf[q++] = *yy++;
|
||||||
|
fltbuf[q] = QSE_T('\0');
|
||||||
|
sp = fltbuf;
|
||||||
|
flagc &= ~FLAGC_DOT;
|
||||||
|
width = 0;
|
||||||
|
precision = 0;
|
||||||
|
goto print_lowercase_s;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_nosign:
|
handle_nosign:
|
||||||
sign = 0;
|
sign = 0;
|
||||||
if (lm_flag & LF_J)
|
if (lm_flag & LF_J)
|
||||||
|
{
|
||||||
|
#if defined(__GNUC__) && \
|
||||||
|
(QSE_SIZEOF_UINTMAX_T > QSE_SIZEOF_SIZE_T) && \
|
||||||
|
(QSE_SIZEOF_UINTMAX_T != QSE_SIZEOF_LONG_LONG) && \
|
||||||
|
(QSE_SIZEOF_UINTMAX_T != QSE_SIZEOF_LONG)
|
||||||
|
/* GCC-compiled binaries crashed when getting qse_uintmax_t with va_arg.
|
||||||
|
* This is just a work-around for it */
|
||||||
|
int i;
|
||||||
|
for (i = 0, num = 0; i < QSE_SIZEOF(qse_uintmax_t) / QSE_SIZEOF(qse_size_t); i++)
|
||||||
|
{
|
||||||
|
#if defined(QSE_ENDIAN_BIG)
|
||||||
|
num = num << (8 * QSE_SIZEOF(qse_size_t)) | (va_arg (ap, qse_size_t));
|
||||||
|
#else
|
||||||
|
register int shift = i * QSE_SIZEOF(qse_size_t);
|
||||||
|
qse_size_t x = va_arg (ap, qse_size_t);
|
||||||
|
num |= (qse_uintmax_t)x << (shift * 8);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#else
|
||||||
num = va_arg (ap, qse_uintmax_t);
|
num = va_arg (ap, qse_uintmax_t);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#if (QSE_SIZEOF_LONG_LONG > 0)
|
#if (QSE_SIZEOF_LONG_LONG > 0)
|
||||||
else if (lm_flag & LF_Q)
|
else if (lm_flag & LF_Q)
|
||||||
num = va_arg (ap, unsigned long long int);
|
num = va_arg (ap, unsigned long long int);
|
||||||
@ -417,11 +540,34 @@ handle_nosign:
|
|||||||
|
|
||||||
handle_sign:
|
handle_sign:
|
||||||
if (lm_flag & LF_J)
|
if (lm_flag & LF_J)
|
||||||
|
{
|
||||||
|
#if defined(__GNUC__) && \
|
||||||
|
(QSE_SIZEOF_INTMAX_T > QSE_SIZEOF_SIZE_T) && \
|
||||||
|
(QSE_SIZEOF_UINTMAX_T != QSE_SIZEOF_LONG_LONG) && \
|
||||||
|
(QSE_SIZEOF_UINTMAX_T != QSE_SIZEOF_LONG)
|
||||||
|
/* GCC-compiled binraries crashed when getting qse_uintmax_t with va_arg.
|
||||||
|
* This is just a work-around for it */
|
||||||
|
int i;
|
||||||
|
for (i = 0, num = 0; i < QSE_SIZEOF(qse_intmax_t) / QSE_SIZEOF(qse_size_t); i++)
|
||||||
|
{
|
||||||
|
#if defined(QSE_ENDIAN_BIG)
|
||||||
|
num = num << (8 * QSE_SIZEOF(qse_size_t)) | (va_arg (ap, qse_size_t));
|
||||||
|
#else
|
||||||
|
register int shift = i * QSE_SIZEOF(qse_size_t);
|
||||||
|
qse_size_t x = va_arg (ap, qse_size_t);
|
||||||
|
num |= (qse_uintmax_t)x << (shift * 8);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#else
|
||||||
num = va_arg (ap, qse_intmax_t);
|
num = va_arg (ap, qse_intmax_t);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if (QSE_SIZEOF_LONG_LONG > 0)
|
#if (QSE_SIZEOF_LONG_LONG > 0)
|
||||||
else if (lm_flag & LF_Q)
|
else if (lm_flag & LF_Q)
|
||||||
num = va_arg (ap, long long int);
|
num = va_arg (ap, long long int);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
else if (lm_flag & LF_T)
|
else if (lm_flag & LF_T)
|
||||||
num = va_arg(ap, ptrdiff_t);
|
num = va_arg(ap, ptrdiff_t);
|
||||||
@ -503,11 +649,13 @@ number:
|
|||||||
{
|
{
|
||||||
while (width-- > 0) PUT_CHAR (padc);
|
while (width-- > 0) PUT_CHAR (padc);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
invalid_format:
|
||||||
|
while (percent < fmt) PUT_CHAR(*percent++);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
invalid_format:
|
|
||||||
while (percent < fmt) PUT_CHAR(*percent++);
|
while (percent < fmt) PUT_CHAR(*percent++);
|
||||||
/*
|
/*
|
||||||
* Since we ignore an formatting argument it is no
|
* Since we ignore an formatting argument it is no
|
||||||
|
Loading…
Reference in New Issue
Block a user