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 */
|
/* long double */
|
||||||
LF_LD = (1 << 7),
|
LF_LD = (1 << 7),
|
||||||
/* __float128 */
|
/* __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
|
static struct
|
||||||
{
|
{
|
||||||
hawk_uint8_t flag; /* for single occurrence */
|
hawk_uint16_t flag; /* for single occurrence */
|
||||||
hawk_uint8_t dflag; /* for double occurrence */
|
hawk_uint16_t dflag; /* for double occurrence */
|
||||||
} lm_tab[26] =
|
} lm_tab[26] =
|
||||||
{
|
{
|
||||||
{ 0, 0 }, /* a */
|
{ 0, 0 }, /* a */
|
||||||
@ -115,7 +164,7 @@ static struct
|
|||||||
{ 0, 0 }, /* g */
|
{ 0, 0 }, /* g */
|
||||||
{ LF_H, LF_C }, /* h */
|
{ LF_H, LF_C }, /* h */
|
||||||
{ 0, 0 }, /* i */
|
{ 0, 0 }, /* i */
|
||||||
{ LF_J, 0 }, /* j */
|
{ LF_J, LF_JJ }, /* j */
|
||||||
{ 0, 0 }, /* k */
|
{ 0, 0 }, /* k */
|
||||||
{ LF_L, LF_Q }, /* l */
|
{ LF_L, LF_Q }, /* l */
|
||||||
{ 0, 0 }, /* m */
|
{ 0, 0 }, /* m */
|
||||||
@ -129,7 +178,7 @@ static struct
|
|||||||
{ 0, 0 }, /* u */
|
{ 0, 0 }, /* u */
|
||||||
{ 0, 0 }, /* v */
|
{ 0, 0 }, /* v */
|
||||||
{ 0, 0 }, /* w */
|
{ 0, 0 }, /* w */
|
||||||
{ 0, 0 }, /* z */
|
{ 0, 0 }, /* x */
|
||||||
{ 0, 0 }, /* y */
|
{ 0, 0 }, /* y */
|
||||||
{ LF_Z, 0 }, /* z */
|
{ LF_Z, 0 }, /* z */
|
||||||
};
|
};
|
||||||
@ -704,7 +753,7 @@ static int fmt_outv (hawk_fmtout_t* fmtout, va_list ap)
|
|||||||
/* end of length modifiers */
|
/* end of length modifiers */
|
||||||
|
|
||||||
case 'n': /* number of characters printed so far */
|
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;
|
*(va_arg(ap, hawk_intmax_t*)) = fmtout->count;
|
||||||
else if (lm_flag & LF_Z) /* z */
|
else if (lm_flag & LF_Z) /* z */
|
||||||
*(va_arg(ap, hawk_ooi_t*)) = fmtout->count;
|
*(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 (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||||
if (lm_flag & LF_L) goto uppercase_c;
|
if (lm_flag & LF_L) goto uppercase_c;
|
||||||
#if defined(HAWK_OOCH_IS_UCH)
|
#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
|
#endif
|
||||||
lowercase_c:
|
lowercase_c:
|
||||||
bch = HAWK_SIZEOF(hawk_bch_t) < HAWK_SIZEOF(int)? va_arg(ap, int): va_arg(ap, hawk_bch_t);
|
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 (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||||
if (lm_flag & LF_H) goto lowercase_c;
|
if (lm_flag & LF_H) goto lowercase_c;
|
||||||
#if defined(HAWK_OOCH_IS_BCH)
|
#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
|
#endif
|
||||||
uppercase_c:
|
uppercase_c:
|
||||||
uch = HAWK_SIZEOF(hawk_uch_t) < HAWK_SIZEOF(int)? va_arg(ap, int): va_arg(ap, hawk_uch_t);
|
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 (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||||
if (lm_flag & LF_L) goto uppercase_s;
|
if (lm_flag & LF_L) goto uppercase_s;
|
||||||
#if defined(HAWK_OOCH_IS_UCH)
|
#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
|
#endif
|
||||||
lowercase_s:
|
lowercase_s:
|
||||||
bsp = va_arg(ap, hawk_bch_t*);
|
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 (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||||
if (lm_flag & LF_H) goto lowercase_s;
|
if (lm_flag & LF_H) goto lowercase_s;
|
||||||
#if defined(HAWK_OOCH_IS_UCH)
|
#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
|
#endif
|
||||||
uppercase_s:
|
uppercase_s:
|
||||||
usp = va_arg(ap, hawk_uch_t*);
|
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
|
#error Unsupported hawk_flt_t
|
||||||
#endif
|
#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)
|
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)
|
/* precedence goes to double if sizeof(double) == sizeof(long double)
|
||||||
* for example, %Lf didn't work on some old platforms.
|
* for example, %Lf didn't work on some old platforms.
|
||||||
* so i prefer the format specifier with no modifier.
|
* so i prefer the format specifier with no modifier.
|
||||||
*/
|
*/
|
||||||
#if HAWK_SIZEOF_FLT_T == HAWK_SIZEOF_DOUBLE
|
#if HAWK_SIZEOF_FLTBAS_T == HAWK_SIZEOF_DOUBLE
|
||||||
v.d = va_arg(ap, hawk_flt_t);
|
v.d = va_arg(ap, hawk_fltbas_t);
|
||||||
#elif HAWK_SIZEOF_FLT_T == HAWK_SIZEOF_LONG_DOUBLE
|
#elif HAWK_SIZEOF_FLTBAS_T == HAWK_SIZEOF_LONG_DOUBLE
|
||||||
v.ld = va_arg(ap, hawk_flt_t);
|
v.ld = va_arg(ap, hawk_fltbas_t);
|
||||||
dtype = LF_LD;
|
dtype = LF_LD;
|
||||||
#else
|
#else
|
||||||
#error Unsupported hawk_flt_t
|
#error Unsupported hawk_fltbas_t
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (lm_flag & (LF_LD | LF_L))
|
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);
|
num = va_arg(ap, hawk_uintmax_t);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else if (lm_flag & LF_JJ)
|
||||||
|
{
|
||||||
|
num = *(hawk_uintmax_t*)va_arg(ap, hawk_uintmax_t*);
|
||||||
|
}
|
||||||
else if (lm_flag & LF_T)
|
else if (lm_flag & LF_T)
|
||||||
num = va_arg(ap, hawk_intptr_t/*hawk_ptrdiff_t*/);
|
num = va_arg(ap, hawk_intptr_t/*hawk_ptrdiff_t*/);
|
||||||
else if (lm_flag & LF_Z)
|
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);
|
num = va_arg(ap, hawk_intmax_t);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else if (lm_flag & LF_JJ)
|
||||||
|
num = *(hawk_intmax_t*)va_arg(ap, hawk_intmax_t*);
|
||||||
|
|
||||||
else if (lm_flag & LF_T)
|
else if (lm_flag & LF_T)
|
||||||
num = va_arg(ap, hawk_intptr_t/*hawk_ptrdiff_t*/);
|
num = va_arg(ap, hawk_intptr_t/*hawk_ptrdiff_t*/);
|
||||||
|
@ -8121,7 +8121,8 @@ wp_mod_main:
|
|||||||
int n;
|
int n;
|
||||||
|
|
||||||
#if defined(HAWK_USE_FLTMAX)
|
#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
|
#else
|
||||||
FMT_CHAR (HAWK_T('z'));
|
FMT_CHAR (HAWK_T('z'));
|
||||||
#endif
|
#endif
|
||||||
@ -8159,7 +8160,12 @@ wp_mod_main:
|
|||||||
hawk_rtx_refdownval (rtx, v);
|
hawk_rtx_refdownval (rtx, v);
|
||||||
if (n <= -1) return HAWK_NULL;
|
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;
|
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'))
|
else if (fmt[i] == HAWK_T('c'))
|
||||||
{
|
{
|
||||||
@ -8932,7 +8938,8 @@ wp_mod_main:
|
|||||||
int n;
|
int n;
|
||||||
|
|
||||||
#if defined(HAWK_USE_FLTMAX)
|
#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
|
#else
|
||||||
FMT_MCHAR (HAWK_BT('z'));
|
FMT_MCHAR (HAWK_BT('z'));
|
||||||
#endif
|
#endif
|
||||||
@ -8970,7 +8977,12 @@ wp_mod_main:
|
|||||||
hawk_rtx_refdownval (rtx, v);
|
hawk_rtx_refdownval (rtx, v);
|
||||||
if (n <= -1) return HAWK_NULL;
|
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;
|
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'))
|
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_ooch_t buf[96];
|
||||||
|
|
||||||
hawk_fmttooocstr (hawk,
|
|
||||||
buf, HAWK_COUNTOF(buf),
|
|
||||||
#if defined(HAWK_USE_FLTMAX)
|
#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
|
#else
|
||||||
HAWK_T("%zf"),
|
hawk_fmttooocstr (hawk, buf, HAWK_COUNTOF(buf), HAWK_T("%zf"), ((hawk_nde_flt_t*)nde)->val);
|
||||||
#endif
|
#endif
|
||||||
((hawk_nde_flt_t*)nde)->val
|
|
||||||
);
|
|
||||||
|
|
||||||
PUT_SRCSTR (hawk, buf);
|
PUT_SRCSTR (hawk, buf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2864,13 +2864,16 @@ void hawk_dprintval (hawk_rtx_t* run, hawk_val_t* val)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case HAWK_VAL_INT:
|
case HAWK_VAL_INT:
|
||||||
hawk_errputstrf (HAWK_T("%jd"),
|
hawk_errputstrf (HAWK_T("%jd"), (hawk_intmax_t)((hawk_val_int_t*)val)->val);
|
||||||
(hawk_intmax_t)((hawk_val_int_t*)val)->val);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HAWK_VAL_FLT:
|
case HAWK_VAL_FLT:
|
||||||
hawk_errputstrf (HAWK_T("%jf"),
|
#if defined(HAWK_USE_FLTMAX)
|
||||||
(hawk_fltmax_t)((hawk_val_flt_t*)val)->val);
|
/*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;
|
break;
|
||||||
|
|
||||||
case HAWK_VAL_STR:
|
case HAWK_VAL_STR:
|
||||||
|
Loading…
Reference in New Issue
Block a user