touched up floating-point number formatting code

This commit is contained in:
hyunghwan.chung 2019-11-23 04:21:07 +00:00
parent 3ced20346c
commit 474fcebe21
3 changed files with 101 additions and 104 deletions

View File

@ -67,6 +67,8 @@
#include "moo-prv.h" #include "moo-prv.h"
#if defined(MOO_ENABLE_FLTFMT)
#include <stdio.h> /* for snrintf(). used for floating-point number formatting */ #include <stdio.h> /* for snrintf(). used for floating-point number formatting */
#if defined(_MSC_VER) || defined(__BORLANDC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1200)) #if defined(_MSC_VER) || defined(__BORLANDC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1200))
# define snprintf _snprintf # define snprintf _snprintf
@ -78,6 +80,8 @@
# include <quadmath.h> /* for quadmath_snprintf() */ # include <quadmath.h> /* for quadmath_snprintf() */
#endif #endif
#endif /* MOO_ENABLE_FLTFMT)
/* Max number conversion buffer length: /* Max number conversion buffer length:
* moo_intmax_t in base 2, plus NUL byte. */ * moo_intmax_t in base 2, plus NUL byte. */
#define MAXNBUF (MOO_SIZEOF(moo_intmax_t) * MOO_BITS_PER_BYTE + 1) #define MAXNBUF (MOO_SIZEOF(moo_intmax_t) * MOO_BITS_PER_BYTE + 1)
@ -413,6 +417,25 @@ static int fmt_outv (moo_fmtout_t* fmtout, va_list ap)
moo_bch_t nbuf[MAXNBUF]; moo_bch_t nbuf[MAXNBUF];
const moo_bch_t* nbufp; const moo_bch_t* nbufp;
int stop = 0; int stop = 0;
#if defined(MOO_ENABLE_FLTFMT)
struct
{
struct
{
moo_bch_t sbuf[32];
moo_bch_t* ptr;
moo_oow_t capa;
} fmt;
struct
{
moo_bch_t sbuf[64];
moo_bch_t* ptr;
moo_oow_t capa;
} out;
} fb; /* some buffers for handling float-point number formatting */
#endif
moo_bch_t* (*sprintn) (moo_bch_t* nbuf, moo_uintmax_t num, int base, moo_ooi_t* lenp); moo_bch_t* (*sprintn) (moo_bch_t* nbuf, moo_uintmax_t num, int base, moo_ooi_t* lenp);
fmtptr = (const moo_uint8_t*)fmtout->fmt_str; fmtptr = (const moo_uint8_t*)fmtout->fmt_str;
@ -428,11 +451,12 @@ static int fmt_outv (moo_fmtout_t* fmtout, va_list ap)
/* this is an internal function. it doesn't reset count to 0 */ /* this is an internal function. it doesn't reset count to 0 */
/* fmtout->count = 0; */ /* fmtout->count = 0; */
#if defined(MOO_ENABLE_FLTFMT)
fmtout->fb.fmt.ptr = fmtout->fb.fmt.sbuf; fb.fmt.ptr = fb.fmt.sbuf;
fmtout->fb.fmt.capa = MOO_COUNTOF(fmtout->fb.fmt.sbuf) - 1; fb.fmt.capa = MOO_COUNTOF(fb.fmt.sbuf) - 1;
fmtout->fb.out.ptr = fmtout->fb.out.sbuf; fb.out.ptr = fb.out.sbuf;
fmtout->fb.out.capa = MOO_COUNTOF(fmtout->fb.out.sbuf) - 1; fb.out.capa = MOO_COUNTOF(fb.out.sbuf) - 1;
#endif
while (1) while (1)
{ {
@ -500,6 +524,8 @@ static int fmt_outv (moo_fmtout_t* fmtout, va_list ap)
case MOO_FMTOUT_FMT_TYPE_UCH: case MOO_FMTOUT_FMT_TYPE_UCH:
uch = *(const moo_uch_t*)fmtptr; uch = *(const moo_uch_t*)fmtptr;
break; break;
default: /* this must not happen */
goto oops;
} }
fmtptr += fmtchsz; fmtptr += fmtchsz;
@ -545,7 +571,6 @@ static int fmt_outv (moo_fmtout_t* fmtout, va_list ap)
flagc &= ~FLAGC_ZEROPAD; flagc &= ~FLAGC_ZEROPAD;
} }
} }
goto reswitch; goto reswitch;
case '*': /* take the length from the parameter */ case '*': /* take the length from the parameter */
@ -996,6 +1021,7 @@ static int fmt_outv (moo_fmtout_t* fmtout, va_list ap)
break; break;
} }
#if defined(MOO_ENABLE_FLTFMT)
case 'e': case 'e':
case 'E': case 'E':
case 'f': case 'f':
@ -1075,59 +1101,59 @@ static int fmt_outv (moo_fmtout_t* fmtout, va_list ap)
} }
fmtlen = fmtptr - percent; fmtlen = fmtptr - percent;
if (fmtlen > fmtout->fb.fmt.capa) if (fmtlen > fb.fmt.capa)
{ {
if (fmtout->fb.fmt.ptr == fmtout->fb.fmt.sbuf) if (fb.fmt.ptr == fb.fmt.sbuf)
{ {
fmtout->fb.fmt.ptr = (moo_bch_t*)MOO_MMGR_ALLOC(fmtout->mmgr, MOO_SIZEOF(*fmtout->fb.fmt.ptr) * (fmtlen + 1)); fb.fmt.ptr = (moo_bch_t*)MOO_MMGR_ALLOC(fmtout->mmgr, MOO_SIZEOF(*fb.fmt.ptr) * (fmtlen + 1));
if (!fmtout->fb.fmt.ptr) goto oops; if (!fb.fmt.ptr) goto oops;
} }
else else
{ {
moo_bch_t* tmpptr; moo_bch_t* tmpptr;
tmpptr = (moo_bch_t*)MOO_MMGR_REALLOC(fmtout->mmgr, fmtout->fb.fmt.ptr, MOO_SIZEOF(*fmtout->fb.fmt.ptr) * (fmtlen + 1)); tmpptr = (moo_bch_t*)MOO_MMGR_REALLOC(fmtout->mmgr, fb.fmt.ptr, MOO_SIZEOF(*fb.fmt.ptr) * (fmtlen + 1));
if (!tmpptr) goto oops; if (!tmpptr) goto oops;
fmtout->fb.fmt.ptr = tmpptr; fb.fmt.ptr = tmpptr;
} }
fmtout->fb.fmt.capa = fmtlen; fb.fmt.capa = fmtlen;
} }
/* compose back the format specifier */ /* compose back the format specifier */
fmtlen = 0; fmtlen = 0;
fmtout->fb.fmt.ptr[fmtlen++] = '%'; fb.fmt.ptr[fmtlen++] = '%';
if (flagc & FLAGC_SPACE) fmtout->fb.fmt.ptr[fmtlen++] = ' '; if (flagc & FLAGC_SPACE) fb.fmt.ptr[fmtlen++] = ' ';
if (flagc & FLAGC_SHARP) fmtout->fb.fmt.ptr[fmtlen++] = '#'; if (flagc & FLAGC_SHARP) fb.fmt.ptr[fmtlen++] = '#';
if (flagc & FLAGC_SIGN) fmtout->fb.fmt.ptr[fmtlen++] = '+'; if (flagc & FLAGC_SIGN) fb.fmt.ptr[fmtlen++] = '+';
if (flagc & FLAGC_LEFTADJ) fmtout->fb.fmt.ptr[fmtlen++] = '-'; if (flagc & FLAGC_LEFTADJ) fb.fmt.ptr[fmtlen++] = '-';
if (flagc & FLAGC_ZEROPAD) fmtout->fb.fmt.ptr[fmtlen++] = '0'; if (flagc & FLAGC_ZEROPAD) fb.fmt.ptr[fmtlen++] = '0';
if (flagc & FLAGC_STAR1) fmtout->fb.fmt.ptr[fmtlen++] = '*'; if (flagc & FLAGC_STAR1) fb.fmt.ptr[fmtlen++] = '*';
else if (flagc & FLAGC_WIDTH) else if (flagc & FLAGC_WIDTH)
{ {
fmtlen += moo_fmt_uintmax_to_bcstr( fmtlen += moo_fmt_uintmax_to_bcstr(
&fmtout->fb.fmt.ptr[fmtlen], fmtout->fb.fmt.capa - fmtlen, &fb.fmt.ptr[fmtlen], fb.fmt.capa - fmtlen,
width, 10, -1, '\0', MOO_NULL); width, 10, -1, '\0', MOO_NULL);
} }
if (flagc & FLAGC_DOT) fmtout->fb.fmt.ptr[fmtlen++] = '.'; if (flagc & FLAGC_DOT) fb.fmt.ptr[fmtlen++] = '.';
if (flagc & FLAGC_STAR2) fmtout->fb.fmt.ptr[fmtlen++] = '*'; if (flagc & FLAGC_STAR2) fb.fmt.ptr[fmtlen++] = '*';
else if (flagc & FLAGC_PRECISION) else if (flagc & FLAGC_PRECISION)
{ {
fmtlen += moo_fmt_uintmax_to_bcstr( fmtlen += moo_fmt_uintmax_to_bcstr(
&fmtout->fb.fmt.ptr[fmtlen], fmtout->fb.fmt.capa - fmtlen, &fb.fmt.ptr[fmtlen], fb.fmt.capa - fmtlen,
precision, 10, -1, '\0', MOO_NULL); precision, 10, -1, '\0', MOO_NULL);
} }
if (dtype == LF_LD) if (dtype == LF_LD)
fmtout->fb.fmt.ptr[fmtlen++] = 'L'; fb.fmt.ptr[fmtlen++] = 'L';
#if (MOO_SIZEOF___FLOAT128 > 0) #if (MOO_SIZEOF___FLOAT128 > 0)
else if (dtype == LF_QD) else if (dtype == LF_QD)
fmtout->fb.fmt.ptr[fmtlen++] = 'Q'; fb.fmt.ptr[fmtlen++] = 'Q';
#endif #endif
fmtout->fb.fmt.ptr[fmtlen++] = uch; fb.fmt.ptr[fmtlen++] = uch;
fmtout->fb.fmt.ptr[fmtlen] = '\0'; fb.fmt.ptr[fmtlen] = '\0';
#if defined(HAVE_SNPRINTF) #if defined(HAVE_SNPRINTF)
/* nothing special here */ /* nothing special here */
@ -1147,88 +1173,65 @@ static int fmt_outv (moo_fmtout_t* fmtout, va_list ap)
while (1) while (1)
{ {
if (dtype == LF_LD) if (dtype == LF_LD)
{ {
#if defined(HAVE_SNPRINTF) #if defined(HAVE_SNPRINTF)
q = snprintf((moo_bch_t*)fmtout->fb.out.ptr, fmtout->fb.out.capa + 1, fmtout->fb.fmt.ptr, v.ld); q = snprintf((moo_bch_t*)fb.out.ptr, fb.out.capa + 1, fb.fmt.ptr, v.ld);
#else #else
q = sprintf((moo_bch_t*)fmtout->fb.out.ptr, fmtout->fb.fmt.ptr, v.ld); q = sprintf((moo_bch_t*)fb.out.ptr, fb.fmt.ptr, v.ld);
#endif #endif
} }
#if (MOO_SIZEOF___FLOAT128 > 0) && defined(HAVE_QUADMATH_SNPRINTF) #if (MOO_SIZEOF___FLOAT128 > 0) && defined(HAVE_QUADMATH_SNPRINTF)
else if (dtype == LF_QD) else if (dtype == LF_QD)
{ {
q = quadmath_snprintf((moo_bch_t*)fmtout->fb.out.ptr, fmtout->fb.out.capa + 1, fmtout->fb.fmt.ptr, v.qd); q = quadmath_snprintf((moo_bch_t*)fb.out.ptr, fb.out.capa + 1, fb.fmt.ptr, v.qd);
} }
#endif #endif
else else
{ {
#if defined(HAVE_SNPRINTF) #if defined(HAVE_SNPRINTF)
q = snprintf((moo_bch_t*)fmtout->fb.out.ptr, fmtout->fb.out.capa + 1, fmtout->fb.fmt.ptr, v.d); q = snprintf((moo_bch_t*)fb.out.ptr, fb.out.capa + 1, fb.fmt.ptr, v.d);
#else #else
q = sprintf((moo_bch_t*)fmtout->fb.out.ptr, fmtout->fb.fmt.ptr, v.d); q = sprintf((moo_bch_t*)fb.out.ptr, fb.fmt.ptr, v.d);
#endif #endif
} }
if (q <= -1) goto oops; if (q <= -1) goto oops;
if (q <= fmtout->fb.out.capa) break; if (q <= fb.out.capa) break;
newcapa = fmtout->fb.out.capa * 2; newcapa = fb.out.capa * 2;
if (newcapa < q) newcapa = q; if (newcapa < q) newcapa = q;
if (fmtout->fb.out.ptr == fmtout->fb.out.sbuf) if (fb.out.ptr == fb.out.sbuf)
{ {
fmtout->fb.out.ptr = (moo_bch_t*)MOO_MMGR_ALLOC(fmtout->mmgr, MOO_SIZEOF(char_t) * (newcapa + 1)); fb.out.ptr = (moo_bch_t*)MOO_MMGR_ALLOC(fmtout->mmgr, MOO_SIZEOF(char_t) * (newcapa + 1));
if (!fmtout->fb.out.ptr) goto oops; if (!fb.out.ptr) goto oops;
} }
else else
{ {
moo_bch_t* tmpptr; moo_bch_t* tmpptr;
tmpptr = (moo_bch_t*)MOO_MMGR_REALLOC(fmtout->mmgr, fmtout->fb.out.ptr, MOO_SIZEOF(char_t) * (newcapa + 1)); tmpptr = (moo_bch_t*)MOO_MMGR_REALLOC(fmtout->mmgr, fb.out.ptr, MOO_SIZEOF(char_t) * (newcapa + 1));
if (!tmpptr) goto oops; if (!tmpptr) goto oops;
fmtout->fb.out.ptr = tmpptr; fb.out.ptr = tmpptr;
} }
fmtout->fb.out.capa = newcapa; fb.out.capa = newcapa;
} }
if (MOO_SIZEOF(char_t) != MOO_SIZEOF(moo_bch_t)) if (MOO_SIZEOF(char_t) != MOO_SIZEOF(moo_bch_t))
{ {
fmtout->fb.out.ptr[q] = '\0'; fb.out.ptr[q] = '\0';
while (q > 0) while (q > 0)
{ {
q--; q--;
fmtout->fb.out.ptr[q] = ((moo_bch_t*)fmtout->fb.out.ptr)[q]; fb.out.ptr[q] = ((moo_bch_t*)fb.out.ptr)[q];
} }
} }
#if 0 bsp = fb.out.ptr;
bsp = fmtout->fb.out.ptr; n = 0; while (bsp[n] != '\0') n++;
flagc &= ~FLAGC_DOT;
width = 0;
precision = 0;
goto lowercase_s;
#else
bsp = fmtout->fb.out.ptr;
n = 0;
/*
if (flagc & FLAGC_DOT)
{
while (n < precision && bsp[n]) n++;
}
else
{*/
while (bsp[n]) n++;
/*}*/
width -= n;
if (!(flagc & FLAGC_LEFTADJ) && width > 0) PUT_BCH (fmtout, padc, width);
PUT_BCS (fmtout, bsp, n); PUT_BCS (fmtout, bsp, n);
if ((flagc & FLAGC_LEFTADJ) && width > 0) PUT_BCH (fmtout, padc, width);
break; break;
#endif
} }
#endif
handle_nosign: handle_nosign:
sign = 0; sign = 0;
@ -1422,9 +1425,17 @@ static int fmt_outv (moo_fmtout_t* fmtout, va_list ap)
} }
done: done:
#if defined(MOO_ENABLE_FLTFMT)
if (fb.fmt.ptr != fb.fmt.sbuf) MOO_MMGR_FREE (fmtout->mmgr, fb.fmt.ptr);
if (fb.out.ptr != fb.out.sbuf) MOO_MMGR_FREE (fmtout->mmgr, fb.out.ptr);
#endif
return 0; return 0;
oops: oops:
#if defined(MOO_ENABLE_FLTFMT)
if (fb.fmt.ptr != fb.fmt.sbuf) MOO_MMGR_FREE (fmtout->mmgr, fb.fmt.ptr);
if (fb.out.ptr != fb.out.sbuf) MOO_MMGR_FREE (fmtout->mmgr, fb.out.ptr);
#endif
return -1; return -1;
} }
@ -2944,5 +2955,3 @@ int moo_strfmtcallstack (moo_t* moo, moo_ooi_t nargs, int rcv_is_fmtstr)
moo->sprintf.xbuf.len = 0; moo->sprintf.xbuf.len = 0;
return format_stack_args(&fo, nargs, rcv_is_fmtstr); return format_stack_args(&fo, nargs, rcv_is_fmtstr);
} }

View File

@ -181,25 +181,10 @@ struct moo_fmtout_t
moo_bitmask_t mask; /* in */ moo_bitmask_t mask; /* in */
void* ctx; /* in */ void* ctx; /* in */
/* internally set as input */
moo_fmtout_fmt_type_t fmt_type; moo_fmtout_fmt_type_t fmt_type;
const void* fmt_str; const void* fmt_str;
/* internal use from here below */
struct
{
struct
{
moo_bch_t sbuf[32];
moo_bch_t* ptr;
moo_oow_t capa;
} fmt;
struct
{
moo_bch_t sbuf[32];
moo_bch_t* ptr;
moo_oow_t capa;
} out;
} fb; /* some buffers for handling moo_flt_t/moo_fltmax_t formatting */
}; };
#if defined(__cplusplus) #if defined(__cplusplus)
@ -258,10 +243,10 @@ extern "C" {
*/ */
MOO_EXPORT int moo_fmt_intmax_to_bcstr ( MOO_EXPORT int moo_fmt_intmax_to_bcstr (
moo_bch_t* buf, /**< buffer pointer */ moo_bch_t* buf, /**< buffer pointer */
int bufsize, /**< buffer size */ int bufsize, /**< buffer size */
moo_intmax_t value, /**< integer to format */ moo_intmax_t value, /**< integer to format */
int base_and_flags, /**< base ORed with flags */ int base_and_flags, /**< base ORed with flags */
int precision, /**< precision */ int precision, /**< precision */
moo_bch_t fillchar, /**< fill character */ moo_bch_t fillchar, /**< fill character */
const moo_bch_t* prefix /**< prefix */ const moo_bch_t* prefix /**< prefix */
); );
@ -318,10 +303,10 @@ MOO_EXPORT int moo_fmt_intmax_to_bcstr (
*/ */
MOO_EXPORT int moo_fmt_intmax_to_ucstr ( MOO_EXPORT int moo_fmt_intmax_to_ucstr (
moo_uch_t* buf, /**< buffer pointer */ moo_uch_t* buf, /**< buffer pointer */
int bufsize, /**< buffer size */ int bufsize, /**< buffer size */
moo_intmax_t value, /**< integer to format */ moo_intmax_t value, /**< integer to format */
int base_and_flags, /**< base ORed with flags */ int base_and_flags, /**< base ORed with flags */
int precision, /**< precision */ int precision, /**< precision */
moo_uch_t fillchar, /**< fill character */ moo_uch_t fillchar, /**< fill character */
const moo_uch_t* prefix /**< prefix */ const moo_uch_t* prefix /**< prefix */
); );

View File

@ -50,14 +50,8 @@
#define MOO_KARATSUBA_CUTOFF 32 #define MOO_KARATSUBA_CUTOFF 32
#define MOO_KARATSUBA_CUTOFF_DEBUG 3 #define MOO_KARATSUBA_CUTOFF_DEBUG 3
#if defined(MOO_BUILD_DEBUG) /* enable floating-pointer number support in the basic formatting functions */
/*#define MOO_DEBUG_LEXER 1*/ #define MOO_ENABLE_FLTFMT
#define MOO_DEBUG_COMPILER 1
#define MOO_DEBUG_VM_PROCESSOR 1
/*#define MOO_DEBUG_VM_EXEC 1*/
#define MOO_PROFILE_VM 1
#endif
/* allow the caller to drive process switching by calling /* allow the caller to drive process switching by calling
* moo_switchprocess(). */ * moo_switchprocess(). */
@ -71,6 +65,15 @@
#define MOO_LIMIT_OBJ_SIZE #define MOO_LIMIT_OBJ_SIZE
#if defined(MOO_BUILD_DEBUG)
/*#define MOO_DEBUG_LEXER 1*/
#define MOO_DEBUG_COMPILER 1
#define MOO_DEBUG_VM_PROCESSOR 1
/*#define MOO_DEBUG_VM_EXEC 1*/
#define MOO_PROFILE_VM 1
#endif /* MOO_BUILD_DEBUG */
#if defined(__has_builtin) #if defined(__has_builtin)
# if (!__has_builtin(__builtin_memset) || !__has_builtin(__builtin_memcpy) || !__has_builtin(__builtin_memmove) || !__has_builtin(__builtin_memcmp)) # if (!__has_builtin(__builtin_memset) || !__has_builtin(__builtin_memcpy) || !__has_builtin(__builtin_memmove) || !__has_builtin(__builtin_memcmp))