diff --git a/qse/include/qse/types.h b/qse/include/qse/types.h index bf9191d3..210d3993 100644 --- a/qse/include/qse/types.h +++ b/qse/include/qse/types.h @@ -481,6 +481,12 @@ typedef qse_int_t qse_intptr_t; # define QSE_SIZEOF_FLTMAX_T QSE_SIZEOF_FLT_T #endif + +/** @typedef qse_ptrdiff_t + */ +typedef qse_ssize_t qse_ptrdiff_t; +#define QSE_SIZEOF_PTRDIFF_T QSE_SIZEOF_SSIZE_T + /** * The qse_mchar_t type defines a multi-byte character type. */ diff --git a/qse/lib/cmn/printf.c b/qse/lib/cmn/printf.c index 18383087..1c04e525 100644 --- a/qse/lib/cmn/printf.c +++ b/qse/lib/cmn/printf.c @@ -40,10 +40,11 @@ enum LF_J = (1 << 2), LF_L = (1 << 3), LF_Q = (1 << 4), - LF_Z = (1 << 5), + LF_T = (1 << 5), + LF_Z = (1 << 6), /* long double */ - LF_LD = (1 << 6) + LF_LD = (1 << 7) }; static struct @@ -71,7 +72,7 @@ static struct { LF_Q, 0 }, /* q */ { 0, 0 }, /* r */ { 0, 0 }, /* s */ - { 0, 0 }, /* t */ + { LF_T, 0 }, /* t */ { 0, 0 }, /* u */ { 0, 0 }, /* v */ { 0, 0 }, /* w */ @@ -97,6 +98,10 @@ enum }; #include /* TODO: remove dependency on this */ +#if defined(_MSC_VER) || defined(__BORLANDC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1200)) +# define snprintf _snprintf +# define vsnprintf _vsnprintf +#endif static int put_wchar (qse_wchar_t c, void *arg) { @@ -186,8 +191,7 @@ int qse_mvprintf (const char_t* fmt, va_list ap) #define sprintn w_sprintn #define xprintf qse_wxprintf -static const qse_wchar_t w_hex2ascii[] = - QSE_WT("0123456789abcdefghijklmnopqrstuvwxyz"); +static const qse_wchar_t w_hex2ascii[] = QSE_WT("0123456789abcdefghijklmnopqrstuvwxyz"); #define hex2ascii(hex) (w_hex2ascii[hex]) #include "printf.h" diff --git a/qse/lib/cmn/printf.h b/qse/lib/cmn/printf.h index 6962b127..bed7caff 100644 --- a/qse/lib/cmn/printf.h +++ b/qse/lib/cmn/printf.h @@ -87,15 +87,15 @@ static char_t* sprintn (char_t* nbuf, qse_uintmax_t num, int base, int *lenp, in /* TODO: error check */ #define PUT_CHAR(c) do { \ if (put_char (c, arg) <= -1) goto oops; \ - retval++; \ + outcnt++; \ } while (0) #define PUT_OCHAR(c) do { \ if (put_ochar (c, arg) <= -1) goto oops; \ - retval++; \ + outcnt++; \ } while (0) -int xprintf (char_t const *fmt, int (*put_char)(char_t, void*), int (*put_ochar) (ochar_t, void*), void *arg, va_list ap) +int xprintf (const char_t* fmt, int (*put_char)(char_t, void*), int (*put_ochar) (ochar_t, void*), void *arg, va_list ap) { char_t nbuf[MAXNBUF]; const char_t* p, * percent; @@ -105,18 +105,34 @@ int xprintf (char_t const *fmt, int (*put_char)(char_t, void*), int (*put_ochar) ochar_t oach, opadc, * osp; int lm_flag, lm_dflag, flagc, numlen; qse_uintmax_t num = 0; - int stop = 0, retval = 0; - char_t fltbuf[100]; + int stop = 0; + int outcnt = 0; - qse_mchar_t fltfmt[64]; - qse_mchar_t* fltfmtp = QSE_NULL; - qse_size_t fltfmtc; + struct + { + qse_mchar_t sbuf[32]; + qse_mchar_t* ptr; + qse_size_t capa; + } fltfmt; + + struct + { + char_t sbuf[96]; + char_t* ptr; + qse_size_t capa; + } fltout; + + fltfmt.ptr = fltfmt.sbuf; + fltfmt.capa = QSE_COUNTOF(fltfmt.sbuf) - 1; + + fltout.ptr = fltout.sbuf; + fltout.capa = QSE_COUNTOF(fltout.sbuf) - 1; while (1) { while ((ch = (uchar_t)*fmt++) != T('%') || stop) { - if (ch == T('\0')) return retval; + if (ch == T('\0')) goto done; PUT_CHAR(ch); } percent = fmt - 1; @@ -248,9 +264,7 @@ reswitch: case T('q'): /* long long int */ case T('j'): /* uintmax_t */ case T('z'): /* size_t */ -#if 0 case T('t'): /* ptrdiff_t */ -#endif if (lm_flag & LF_LD) goto invalid_format; flagc |= FLAGC_LENMOD; @@ -293,31 +307,28 @@ reswitch: /* end of length modifiers */ case T('n'): - if (lm_flag & LF_J) - *(va_arg(ap, qse_intmax_t*)) = retval; + if (lm_flag & LF_J) /* j */ + *(va_arg(ap, qse_intmax_t*)) = outcnt; + else if (lm_flag & LF_Z) /* z */ + *(va_arg(ap, qse_size_t*)) = outcnt; #if (QSE_SIZEOF_LONG_LONG > 0) - else if (lm_flag & LF_Q) - *(va_arg(ap, long long int*)) = retval; + else if (lm_flag & LF_Q) /* ll */ + *(va_arg(ap, long long int*)) = outcnt; #endif - else if (lm_flag & LF_L) - *(va_arg(ap, long int*)) = retval; - else if (lm_flag & LF_Z) - *(va_arg(ap, qse_size_t*)) = retval; - else if (lm_flag & LF_H) - *(va_arg(ap, short int*)) = retval; - else if (lm_flag & LF_C) - *(va_arg(ap, char*)) = retval; + else if (lm_flag & LF_L) /* l */ + *(va_arg(ap, long int*)) = outcnt; + else if (lm_flag & LF_H) /* h */ + *(va_arg(ap, short int*)) = outcnt; + else if (lm_flag & LF_C) /* hh */ + *(va_arg(ap, char*)) = outcnt; else - *(va_arg(ap, int*)) = retval; + *(va_arg(ap, int*)) = outcnt; break; /* signed integer conversions */ case T('d'): case T('i'): /* signed conversion */ - #if defined(NO_MERCY) - if (lm_flag & LF_LD) goto invalid_format; - #endif base = 10; sign = 1; goto handle_sign; @@ -325,31 +336,19 @@ reswitch: /* unsigned integer conversions */ case T('o'): - #if defined(NO_MERCY) - if (lm_flag & LF_LD) goto invalid_format; - #endif base = 8; goto handle_nosign; case T('u'): - #if defined(NO_MERCY) - if (lm_flag & LF_LD) goto invalid_format; - #endif base = 10; goto handle_nosign; case T('X'): upper = 1; case T('x'): - #if defined(NO_MERCY) - if (lm_flag & LF_LD) goto invalid_format; - #endif base = 16; goto handle_nosign; /* end of unsigned integer conversions */ case T('p'): /* pointer */ - #if defined(NO_MERCY) - if (lm_flag & LF_LD) goto invalid_format; - #endif base = 16; if (width == 0) flagc |= FLAGC_SHARP; @@ -470,37 +469,89 @@ reswitch: case T('A'): */ { - qse_mchar_t tmpbuf[100]; - qse_mchar_t* tmpbufp; - - const char_t* xx; - const qse_mchar_t* yy; + /* let me rely on snprintf until i implement + * float-point to string conversion */ int q; + qse_size_t fmtlen; + qse_fltmax_t v_fltmax; + long double v_ld; + double v_d; - #if defined(NO_MERCY) - if (lm_flag & ~LF_LD) goto invalid_format; - #endif - - if (fmt - percent < QSE_COUNTOF(fltfmt)) - { - fltfmtp = fltfmt; - } + if (lm_flag & LF_J) + v_fltmax = va_arg (ap, qse_fltmax_t); + else if (lm_flag & (LF_LD | LF_L | LF_Q | LF_Z)) + v_ld = va_arg (ap, long double); else + v_d = va_arg (ap, double); + + fmtlen = fmt - percent; + if (fmtlen > fltfmt.capa) { - fltfmtp = QSE_MMGR_ALLOC (QSE_MMGR_GETDFL(), QSE_SIZEOF(*fltfmtp) * (fmt - percent + 1)); - if (fltfmtp == QSE_NULL) goto oops; + if (fltfmt.ptr == fltfmt.sbuf) + { + fltfmt.ptr = QSE_MMGR_ALLOC (QSE_MMGR_GETDFL(), QSE_SIZEOF(*fltfmt.ptr) * (fmtlen + 1)); + if (fltfmt.ptr == QSE_NULL) goto oops; + } + else + { + qse_mchar_t* tmpptr; + + tmpptr = QSE_MMGR_REALLOC (QSE_MMGR_GETDFL(), fltfmt.ptr, QSE_SIZEOF(*fltfmt.ptr) * (fmtlen + 1)); + if (tmpptr == QSE_NULL) goto oops; + fltfmt.ptr = tmpptr; + } + + fltfmt.capa = fmtlen; } - for (xx = percent, q = 0; xx < fmt; xx++) fltfmtp[q++] = *xx; - fltfmtp[q] = QSE_MT('\0'); - if (lm_flag & LF_LD) - snprintf (tmpbuf, QSE_SIZEOF(tmpbuf), fltfmtp, va_arg (ap, long double)); - else - snprintf (tmpbuf, QSE_SIZEOF(tmpbuf), fltfmtp, va_arg (ap, double)); + fltfmt.ptr[fmtlen] = QSE_MT('\0'); + while (fmtlen > 0) + { + fmtlen--; + fltfmt.ptr[fmtlen] = percent[fmtlen]; + } - for (yy = tmpbuf, q = 0; *yy; ) fltbuf[q++] = *yy++; - fltbuf[q] = QSE_T('\0'); - sp = fltbuf; + while (1) + { + qse_size_t newcapa; + + if (lm_flag & LF_J) + q = snprintf ((qse_mchar_t*)fltout.ptr, fltout.capa + 1, fltfmt.ptr, v_fltmax); + else if (lm_flag & (LF_LD | LF_L | LF_Q | LF_Z)) + q = snprintf ((qse_mchar_t*)fltout.ptr, fltout.capa + 1, fltfmt.ptr, v_ld); + else + q = snprintf ((qse_mchar_t*)fltout.ptr, fltout.capa + 1, fltfmt.ptr, v_d); + if (q <= -1) goto oops; + if (q <= fltout.capa) break; + + newcapa = fltout.capa * 2; + if (fltout.ptr == fltout.sbuf) + { + fltout.ptr = QSE_MMGR_ALLOC (QSE_MMGR_GETDFL(), QSE_SIZEOF(char_t) * (newcapa + 1)); + if (fltout.ptr == QSE_NULL) goto oops; + } + else + { + char_t* tmpptr; + + tmpptr = QSE_MMGR_REALLOC (QSE_MMGR_GETDFL(), fltout.ptr, QSE_SIZEOF(char_t) * (newcapa + 1)); + if (tmpptr == QSE_NULL) goto oops; + fltout.ptr = tmpptr; + } + fltout.capa = newcapa; + } + + if (QSE_SIZEOF(char_t) != QSE_SIZEOF(qse_mchar_t)) + { + fltout.ptr[q] = T('\0'); + while (q > 0) + { + q--; + fltout.ptr[q] = ((qse_mchar_t*)fltout.ptr)[q]; + } + } + + sp = fltout.ptr; flagc &= ~FLAGC_DOT; width = 0; precision = 0; @@ -532,20 +583,16 @@ handle_nosign: num = va_arg (ap, qse_uintmax_t); #endif } + else if (lm_flag & LF_T) + num = va_arg (ap, qse_ptrdiff_t); + else if (lm_flag & LF_Z) + num = va_arg (ap, qse_size_t); #if (QSE_SIZEOF_LONG_LONG > 0) else if (lm_flag & LF_Q) num = va_arg (ap, unsigned long long int); #endif - - #if 0 - else if (lm_flag & LF_T) - num = va_arg (ap, ptrdiff_t); - #endif - - else if (lm_flag & LF_L) + else if (lm_flag & (LF_L | LF_LD)) num = va_arg (ap, long int); - else if (lm_flag & LF_Z) - num = va_arg (ap, qse_size_t); else if (lm_flag & LF_H) num = (unsigned short int)va_arg (ap, int); else if (lm_flag & LF_C) @@ -579,19 +626,16 @@ handle_sign: #endif } + else if (lm_flag & LF_T) + num = va_arg(ap, qse_ptrdiff_t); + else if (lm_flag & LF_Z) + num = va_arg (ap, qse_ssize_t); #if (QSE_SIZEOF_LONG_LONG > 0) else if (lm_flag & LF_Q) num = va_arg (ap, long long int); #endif - - #if 0 - else if (lm_flag & LF_T) - num = va_arg(ap, ptrdiff_t); - #endif - else if (lm_flag & LF_L) + else if (lm_flag & (LF_L | LF_LD)) num = va_arg (ap, long int); - else if (lm_flag & LF_Z) - num = va_arg (ap, qse_ssize_t); else if (lm_flag & LF_H) num = (short int)va_arg (ap, int); else if (lm_flag & LF_C) @@ -684,11 +728,18 @@ invalid_format: } } +done: + if (fltfmt.ptr != fltfmt.sbuf) + QSE_MMGR_FREE (QSE_MMGR_GETDFL(), fltfmt.ptr); + if (fltout.ptr != fltout.sbuf) + QSE_MMGR_FREE (QSE_MMGR_GETDFL(), fltout.ptr); + return outcnt; + oops: - if (fltfmtp && fltfmtp != fltfmt) - { - QSE_MMGR_FREE (QSE_MMGR_GETDFL(), fltfmtp); - } + if (fltfmt.ptr != fltfmt.sbuf) + QSE_MMGR_FREE (QSE_MMGR_GETDFL(), fltfmt.ptr); + if (fltout.ptr != fltout.sbuf) + QSE_MMGR_FREE (QSE_MMGR_GETDFL(), fltout.ptr); return -1; } #undef PUT_CHAR