hacked formatting code to work around a compiler problem of not passing __float128 properly via va_list.
introduced 'jj' to pass a large value via a pointer but to take the value inside the pointer changed hawk_rtx_format() and hawk_rtx_formatmbs() to use 'jj' when building with HAWK_USE_FLTMAX on
This commit is contained in:
parent
7827e5fa4b
commit
65ad752666
101
hawk/lib/fmt.c
101
hawk/lib/fmt.c
@ -97,13 +97,62 @@ enum
|
||||
/* long double */
|
||||
LF_LD = (1 << 7),
|
||||
/* __float128 */
|
||||
LF_QD = (1 << 8)
|
||||
LF_QD = (1 << 8),
|
||||
|
||||
/* intmax or fltmax passed as a pointer - introduced to work around the issue where
|
||||
* __float128 value is not passed properly via va_list. for example, the following clode
|
||||
* compiled with clang -O1, -O2, -O3, etc produced a wrong value instead of 9.200000
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
void bbb (const char* fmt, va_list ap)
|
||||
{
|
||||
__float128 x;
|
||||
x = va_arg(ap, __float128);
|
||||
printf ("%Lf\n", (long double)x);
|
||||
}
|
||||
void aaa (const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
bbb (fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
int main ()
|
||||
{
|
||||
__float128 t = 9.2;
|
||||
aaa ("aaaa\n", t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
$ clang --version
|
||||
clang version 7.0.1-8+deb10u2 (tags/RELEASE_701/final)
|
||||
Target: x86_64-pc-linux-gnu
|
||||
Thread model: posix
|
||||
InstalledDir: /usr/bin
|
||||
$ clang -O2 -o a a.c
|
||||
$ ./a
|
||||
0.000000
|
||||
$ clang -O0 -o a a.c
|
||||
$ ./a
|
||||
9.200000
|
||||
|
||||
* the same code printed a correct value without compiler optimization.
|
||||
*
|
||||
* passing a large value via a pointer is a safe way to work around this problem.
|
||||
* hawk_rtx_format() and hawk_rtx_formatmbs() pass 'jj' for a floating-pointer number
|
||||
* when built with HAWK_USE_FLTMAX on.
|
||||
*
|
||||
* 'jj' is allowed for 'c' and 's' but it works like 'j' for them.
|
||||
*/
|
||||
LF_JJ = (1 << 9)
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
hawk_uint8_t flag; /* for single occurrence */
|
||||
hawk_uint8_t dflag; /* for double occurrence */
|
||||
hawk_uint16_t flag; /* for single occurrence */
|
||||
hawk_uint16_t dflag; /* for double occurrence */
|
||||
} lm_tab[26] =
|
||||
{
|
||||
{ 0, 0 }, /* a */
|
||||
@ -115,7 +164,7 @@ static struct
|
||||
{ 0, 0 }, /* g */
|
||||
{ LF_H, LF_C }, /* h */
|
||||
{ 0, 0 }, /* i */
|
||||
{ LF_J, 0 }, /* j */
|
||||
{ LF_J, LF_JJ }, /* j */
|
||||
{ 0, 0 }, /* k */
|
||||
{ LF_L, LF_Q }, /* l */
|
||||
{ 0, 0 }, /* m */
|
||||
@ -129,7 +178,7 @@ static struct
|
||||
{ 0, 0 }, /* u */
|
||||
{ 0, 0 }, /* v */
|
||||
{ 0, 0 }, /* w */
|
||||
{ 0, 0 }, /* z */
|
||||
{ 0, 0 }, /* x */
|
||||
{ 0, 0 }, /* y */
|
||||
{ LF_Z, 0 }, /* z */
|
||||
};
|
||||
@ -704,7 +753,7 @@ static int fmt_outv (hawk_fmtout_t* fmtout, va_list ap)
|
||||
/* end of length modifiers */
|
||||
|
||||
case 'n': /* number of characters printed so far */
|
||||
if (lm_flag & LF_J) /* j */
|
||||
if (lm_flag & (LF_J | LF_JJ)) /* j, jj */
|
||||
*(va_arg(ap, hawk_intmax_t*)) = fmtout->count;
|
||||
else if (lm_flag & LF_Z) /* z */
|
||||
*(va_arg(ap, hawk_ooi_t*)) = fmtout->count;
|
||||
@ -764,7 +813,7 @@ static int fmt_outv (hawk_fmtout_t* fmtout, va_list ap)
|
||||
if (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||
if (lm_flag & LF_L) goto uppercase_c;
|
||||
#if defined(HAWK_OOCH_IS_UCH)
|
||||
if (lm_flag & LF_J) goto uppercase_c;
|
||||
if (lm_flag & (LF_J | LF_JJ)) goto uppercase_c;
|
||||
#endif
|
||||
lowercase_c:
|
||||
bch = HAWK_SIZEOF(hawk_bch_t) < HAWK_SIZEOF(int)? va_arg(ap, int): va_arg(ap, hawk_bch_t);
|
||||
@ -784,7 +833,7 @@ static int fmt_outv (hawk_fmtout_t* fmtout, va_list ap)
|
||||
if (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||
if (lm_flag & LF_H) goto lowercase_c;
|
||||
#if defined(HAWK_OOCH_IS_BCH)
|
||||
if (lm_flag & LF_J) goto lowercase_c;
|
||||
if (lm_flag & (LF_J | LF_JJ)) goto lowercase_c;
|
||||
#endif
|
||||
uppercase_c:
|
||||
uch = HAWK_SIZEOF(hawk_uch_t) < HAWK_SIZEOF(int)? va_arg(ap, int): va_arg(ap, hawk_uch_t);
|
||||
@ -805,7 +854,7 @@ static int fmt_outv (hawk_fmtout_t* fmtout, va_list ap)
|
||||
if (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||
if (lm_flag & LF_L) goto uppercase_s;
|
||||
#if defined(HAWK_OOCH_IS_UCH)
|
||||
if (lm_flag & LF_J) goto uppercase_s;
|
||||
if (lm_flag & (LF_J | LF_JJ)) goto uppercase_s;
|
||||
#endif
|
||||
lowercase_s:
|
||||
bsp = va_arg(ap, hawk_bch_t*);
|
||||
@ -837,7 +886,7 @@ static int fmt_outv (hawk_fmtout_t* fmtout, va_list ap)
|
||||
if (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||
if (lm_flag & LF_H) goto lowercase_s;
|
||||
#if defined(HAWK_OOCH_IS_UCH)
|
||||
if (lm_flag & LF_J) goto lowercase_s;
|
||||
if (lm_flag & (LF_J | LF_JJ)) goto lowercase_s;
|
||||
#endif
|
||||
uppercase_s:
|
||||
usp = va_arg(ap, hawk_uch_t*);
|
||||
@ -1054,21 +1103,35 @@ static int fmt_outv (hawk_fmtout_t* fmtout, va_list ap)
|
||||
#error Unsupported hawk_flt_t
|
||||
#endif
|
||||
}
|
||||
else if (lm_flag & LF_JJ)
|
||||
{
|
||||
#if (HAWK_SIZEOF___FLOAT128 > 0) && defined(HAVE_QUADMATH_SNPRINTF) && (HAWK_SIZEOF_FLTMAX_T == HAWK_SIZEOF___FLOAT128)
|
||||
v.qd = *(hawk_fltmax_t*)va_arg(ap, hawk_fltmax_t*);
|
||||
dtype = LF_QD;
|
||||
#elif HAWK_SIZEOF_FLTMAX_T == HAWK_SIZEOF_DOUBLE
|
||||
v.d = *(hawk_fltmax_t*)va_arg(ap, hawk_fltmax_t*);
|
||||
#elif HAWK_SIZEOF_FLTMAX_T == HAWK_SIZEOF_LONG_DOUBLE
|
||||
v.ld = *(hawk_fltmax_t*)va_arg(ap, hawk_fltmax_t*);
|
||||
dtype = LF_LD;
|
||||
#else
|
||||
#error Unsupported hawk_fltmax_t
|
||||
#endif
|
||||
}
|
||||
else if (lm_flag & LF_Z)
|
||||
{
|
||||
/* hawk_flt_t is limited to double or long double */
|
||||
/* limited to double or long double. use hawk_fltbas_t */
|
||||
|
||||
/* precedence goes to double if sizeof(double) == sizeof(long double)
|
||||
* for example, %Lf didn't work on some old platforms.
|
||||
* so i prefer the format specifier with no modifier.
|
||||
*/
|
||||
#if HAWK_SIZEOF_FLT_T == HAWK_SIZEOF_DOUBLE
|
||||
v.d = va_arg(ap, hawk_flt_t);
|
||||
#elif HAWK_SIZEOF_FLT_T == HAWK_SIZEOF_LONG_DOUBLE
|
||||
v.ld = va_arg(ap, hawk_flt_t);
|
||||
#if HAWK_SIZEOF_FLTBAS_T == HAWK_SIZEOF_DOUBLE
|
||||
v.d = va_arg(ap, hawk_fltbas_t);
|
||||
#elif HAWK_SIZEOF_FLTBAS_T == HAWK_SIZEOF_LONG_DOUBLE
|
||||
v.ld = va_arg(ap, hawk_fltbas_t);
|
||||
dtype = LF_LD;
|
||||
#else
|
||||
#error Unsupported hawk_flt_t
|
||||
#error Unsupported hawk_fltbas_t
|
||||
#endif
|
||||
}
|
||||
else if (lm_flag & (LF_LD | LF_L))
|
||||
@ -1248,6 +1311,10 @@ static int fmt_outv (hawk_fmtout_t* fmtout, va_list ap)
|
||||
num = va_arg(ap, hawk_uintmax_t);
|
||||
#endif
|
||||
}
|
||||
else if (lm_flag & LF_JJ)
|
||||
{
|
||||
num = *(hawk_uintmax_t*)va_arg(ap, hawk_uintmax_t*);
|
||||
}
|
||||
else if (lm_flag & LF_T)
|
||||
num = va_arg(ap, hawk_intptr_t/*hawk_ptrdiff_t*/);
|
||||
else if (lm_flag & LF_Z)
|
||||
@ -1290,6 +1357,8 @@ static int fmt_outv (hawk_fmtout_t* fmtout, va_list ap)
|
||||
num = va_arg(ap, hawk_intmax_t);
|
||||
#endif
|
||||
}
|
||||
else if (lm_flag & LF_JJ)
|
||||
num = *(hawk_intmax_t*)va_arg(ap, hawk_intmax_t*);
|
||||
|
||||
else if (lm_flag & LF_T)
|
||||
num = va_arg(ap, hawk_intptr_t/*hawk_ptrdiff_t*/);
|
||||
|
@ -8121,7 +8121,8 @@ wp_mod_main:
|
||||
int n;
|
||||
|
||||
#if defined(HAWK_USE_FLTMAX)
|
||||
FMT_CHAR (HAWK_T('j'));
|
||||
/*FMT_CHAR (HAWK_T('j'));*/
|
||||
FMT_STR (HAWK_T("jj"), 2); /* see fmt.c for info on jj */
|
||||
#else
|
||||
FMT_CHAR (HAWK_T('z'));
|
||||
#endif
|
||||
@ -8159,7 +8160,12 @@ wp_mod_main:
|
||||
hawk_rtx_refdownval (rtx, v);
|
||||
if (n <= -1) return HAWK_NULL;
|
||||
|
||||
#if defined(HAWK_USE_FLTMAX)
|
||||
/*if (hawk_ooecs_fcat(out, HAWK_OOECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL;*/
|
||||
if (hawk_ooecs_fcat(out, HAWK_OOECS_PTR(fbu), &r) == (hawk_oow_t)-1) return HAWK_NULL;
|
||||
#else
|
||||
if (hawk_ooecs_fcat(out, HAWK_OOECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL;
|
||||
#endif
|
||||
}
|
||||
else if (fmt[i] == HAWK_T('c'))
|
||||
{
|
||||
@ -8932,7 +8938,8 @@ wp_mod_main:
|
||||
int n;
|
||||
|
||||
#if defined(HAWK_USE_FLTMAX)
|
||||
FMT_MCHAR (HAWK_BT('j'));
|
||||
/*FMT_MCHAR (HAWK_BT('j'));*/
|
||||
FMT_MBS (HAWK_BT("jj"), 2); /* see fmt.c for info on jj */
|
||||
#else
|
||||
FMT_MCHAR (HAWK_BT('z'));
|
||||
#endif
|
||||
@ -8970,7 +8977,12 @@ wp_mod_main:
|
||||
hawk_rtx_refdownval (rtx, v);
|
||||
if (n <= -1) return HAWK_NULL;
|
||||
|
||||
#if defined(HAWK_USE_FLTMAX)
|
||||
/*if (hawk_becs_fcat(out, HAWK_BECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL;*/
|
||||
if (hawk_becs_fcat(out, HAWK_BECS_PTR(fbu), &r) == (hawk_oow_t)-1) return HAWK_NULL;
|
||||
#else
|
||||
if (hawk_becs_fcat(out, HAWK_BECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL;
|
||||
#endif
|
||||
}
|
||||
else if (fmt[i] == HAWK_BT('c'))
|
||||
{
|
||||
|
@ -350,16 +350,12 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde)
|
||||
{
|
||||
hawk_ooch_t buf[96];
|
||||
|
||||
hawk_fmttooocstr (hawk,
|
||||
buf, HAWK_COUNTOF(buf),
|
||||
#if defined(HAWK_USE_FLTMAX)
|
||||
HAWK_T("%jf"),
|
||||
/*hawk_fmttooocstr (hawk, buf, HAWK_COUNTOF(buf), HAWK_T("%jf"), ((hawk_nde_flt_t*)nde)->val);*/
|
||||
hawk_fmttooocstr (hawk, buf, HAWK_COUNTOF(buf), HAWK_T("%jjf"), &((hawk_nde_flt_t*)nde)->val);
|
||||
#else
|
||||
HAWK_T("%zf"),
|
||||
hawk_fmttooocstr (hawk, buf, HAWK_COUNTOF(buf), HAWK_T("%zf"), ((hawk_nde_flt_t*)nde)->val);
|
||||
#endif
|
||||
((hawk_nde_flt_t*)nde)->val
|
||||
);
|
||||
|
||||
PUT_SRCSTR (hawk, buf);
|
||||
}
|
||||
break;
|
||||
|
@ -2864,13 +2864,16 @@ void hawk_dprintval (hawk_rtx_t* run, hawk_val_t* val)
|
||||
break;
|
||||
|
||||
case HAWK_VAL_INT:
|
||||
hawk_errputstrf (HAWK_T("%jd"),
|
||||
(hawk_intmax_t)((hawk_val_int_t*)val)->val);
|
||||
hawk_errputstrf (HAWK_T("%jd"), (hawk_intmax_t)((hawk_val_int_t*)val)->val);
|
||||
break;
|
||||
|
||||
case HAWK_VAL_FLT:
|
||||
hawk_errputstrf (HAWK_T("%jf"),
|
||||
(hawk_fltmax_t)((hawk_val_flt_t*)val)->val);
|
||||
#if defined(HAWK_USE_FLTMAX)
|
||||
/*hawk_errputstrf (HAWK_T("%jf"), ((hawk_val_flt_t*)val)->val);*/
|
||||
hawk_errputstrf (HAWK_T("%jjf"), &((hawk_val_flt_t*)val)->val);
|
||||
#else
|
||||
hawk_errputstrf (HAWK_T("%zf"), ((hawk_val_flt_t*)val)->val);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case HAWK_VAL_STR:
|
||||
|
Loading…
Reference in New Issue
Block a user