summaryrefslogtreecommitdiff
path: root/libc/stdio-common/vfscanf.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc/stdio-common/vfscanf.c')
-rw-r--r--libc/stdio-common/vfscanf.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/libc/stdio-common/vfscanf.c b/libc/stdio-common/vfscanf.c
index e4728d00c..5555919f2 100644
--- a/libc/stdio-common/vfscanf.c
+++ b/libc/stdio-common/vfscanf.c
@@ -24,6 +24,9 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
+#ifdef __STDC_DEC_FP__
+#include <dfpstdlib.h>
+#endif
#include <string.h>
#include <wchar.h>
#include <wctype.h>
@@ -67,6 +70,9 @@
#define READ_POINTER 0x1000 /* this is a pointer value */
#define POSIX_MALLOC 0x2000 /* m: malloc strings */
#define MALLOC (GNU_MALLOC | POSIX_MALLOC)
+#ifdef __STDC_DEC_FP__
+#define DECIMAL 0x4000 /* H/D/DD: decimal float */
+#endif
#include <locale/localeinfo.h>
#include <libioP.h>
@@ -583,6 +589,9 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
skip_space = 0;
}
+#ifdef __STDC_DEC_FP__
+found_decimal:
+#endif
switch (fc)
{
case L_('%'): /* Must match a literal '%'. */
@@ -1777,6 +1786,31 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
}
break;
+#ifdef __STDC_DEC_FP__
+ case L_('H'): /* _Decimal32 */
+ base = 10;
+ /*number_signed = 1;*/
+ negative = 1;
+ flags |= DECIMAL | SHORT;
+ fc = *f++;
+ /* Pick up trailing float modifier. */
+ goto found_decimal;
+
+ case L_('D'): /* _Decimal64 */
+ flags |= DECIMAL;
+ base = 10;
+ /*number_signed = 1;*/
+ negative = 1;
+ char tfc;
+ tfc = *f++;
+ if (tfc == L_('D')) /* _Decimal128 */
+ flags |= LONGDBL;
+ else
+ --f; /* Only one 'D'. Back it up. It is not %DD. */
+ fc = *f++;
+ /* Pick up trailing float modifier. */
+ goto found_decimal;
+#endif
case L_('e'): /* Floating-point numbers. */
case L_('E'):
case L_('f'):
@@ -2253,6 +2287,29 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
scan_float:
/* Convert the number. */
ADDW (L_('\0'));
+#ifdef __STDC_DEC_FP__
+ if((flags & DECIMAL) && (flags & SHORT))
+ {
+ _Decimal32 d = __strtod32_internal(wp, &tw, flags & GROUP);
+ if (!(flags & SUPPRESS) && tw != wp)
+ /* va_arg is currently busted in libgcc for _Decimal32 so this
+ * will segfault */
+ *ARG (_Decimal32 *) = negative ? -d : d;
+ }
+ else if((flags & DECIMAL) && (flags & LONGDBL))
+ {
+ _Decimal128 d = __strtod128_internal(wp, &tw, flags & GROUP);
+ if (!(flags & SUPPRESS) && tw != wp)
+ *ARG (_Decimal128 *) = negative ? -d : d;
+ }
+ else if (flags & DECIMAL)
+ {
+ _Decimal64 d = __strtod64_internal(wp, &tw, flags & GROUP);
+ if (!(flags & SUPPRESS) && tw != wp)
+ *ARG (_Decimal64 *) = negative ? -d : d;
+ }
+ else
+#endif
if ((flags & LONGDBL) && !__ldbl_is_dbl)
{
long double d = __strtold_internal (wp, &tw, flags & GROUP);