[CRT]
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 25 May 2014 14:30:54 +0000 (14:30 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 25 May 2014 14:30:54 +0000 (14:30 +0000)
* Partial update of scanf routines. Focus was on the case of reading a float.
* Don't inline float processing, introduce _internal_handle_float() and co to take care of this. Brought to you by Timo.
* Msvcrt scanf tests are now green.
CORE-7005 #resolve #comment Should be fixed in r63443. Thanks Dmitry ;)
CORE-8080

svn path=/trunk/; revision=63443

reactos/lib/sdk/crt/crt.cmake
reactos/lib/sdk/crt/libcntpr.cmake
reactos/lib/sdk/crt/string/scanf.c
reactos/lib/sdk/crt/string/scanf.h
reactos/lib/sdk/crt/string/winesup.c [new file with mode: 0644]
reactos/lib/sdk/crt/string/winesup.h [new file with mode: 0644]

index eae70e5..60aeb56 100644 (file)
@@ -306,6 +306,7 @@ list(APPEND CRT_SOURCE
     string/wtoi.c
     string/wtoi64.c
     string/wtol.c
+    string/winesup.c
     sys_stat/systime.c
     time/asctime.c
     time/clock.c
index 487c92e..6477dfe 100644 (file)
@@ -59,6 +59,7 @@ list(APPEND LIBCNTPR_SOURCE
     string/wtoi64.c
     string/wtoi.c
     string/wtol.c
+    string/winesup.c
     wstring/wcsicmp.c
     wstring/wcslwr.c
     wstring/wcsnicmp.c
index 57c56d0..9ab876f 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include <precomp.h>
-#include <ctype.h>
+#include <stdarg.h>
+#include <limits.h>
 
-// HACK for LIBCNT
-#ifndef debugstr_a
-#define debugstr_a
-#endif
+#include <winternl.h>
+#include <wine/debug.h>
+
+#include "winesup.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
 
 //extern FILE _iob[];
 
@@ -56,49 +58,54 @@ static int wchar2digit(wchar_t c, int base) {
 }
 
 #ifndef _LIBCNT_
-/* vfscanf */
+/* vfscanf_l */
 #undef WIDE_SCANF
 #undef CONSOLE
 #undef STRING
+#undef SECURE
 #include "scanf.h"
 
-/* vfwscanf */
+/* vfwscanf_l */
 #define WIDE_SCANF 1
 #undef CONSOLE
 #undef STRING
+#undef SECURE
 #include "scanf.h"
-#endif
+#endif /* !_LIBCNT_ */
 
-/* vsscanf */
+/* vsscanf_l */
 #undef WIDE_SCANF
 #undef CONSOLE
 #define STRING 1
+#undef SECURE
 #include "scanf.h"
 
-/* vswscanf */
+/* vswscanf_l */
 #define WIDE_SCANF 1
 #undef CONSOLE
 #define STRING 1
+#undef SECURE
 #include "scanf.h"
 
 #ifndef _LIBCNT_
-/* vcscanf */
+/* vcscanf_l */
 #undef WIDE_SCANF
 #define CONSOLE 1
 #undef STRING
+#undef SECURE
 #include "scanf.h"
 
 
 /*********************************************************************
  *             fscanf (MSVCRT.@)
  */
-int fscanf(FILE *file, const char *format, ...)
+int CDECL fscanf(FILE *file, const char *format, ...)
 {
     va_list valist;
     int res;
 
     va_start(valist, format);
-    res = vfscanf(file, format, valist);
+    res = vfscanf_l(file, format, NULL, valist);
     va_end(valist);
     return res;
 }
@@ -106,13 +113,13 @@ int fscanf(FILE *file, const char *format, ...)
 /*********************************************************************
  *             scanf (MSVCRT.@)
  */
-int scanf(const char *format, ...)
+int CDECL scanf(const char *format, ...)
 {
     va_list valist;
     int res;
 
     va_start(valist, format);
-    res = vfscanf(stdin, format, valist);
+    res = vfscanf_l(stdin, format, NULL, valist);
     va_end(valist);
     return res;
 }
@@ -120,13 +127,13 @@ int scanf(const char *format, ...)
 /*********************************************************************
  *             fwscanf (MSVCRT.@)
  */
-int fwscanf(FILE *file, const wchar_t *format, ...)
+int CDECL fwscanf(FILE *file, const wchar_t *format, ...)
 {
     va_list valist;
     int res;
 
     va_start(valist, format);
-    res = vfwscanf(file, format, valist);
+    res = vfwscanf_l(file, format, NULL, valist);
     va_end(valist);
     return res;
 }
@@ -135,29 +142,29 @@ int fwscanf(FILE *file, const wchar_t *format, ...)
 /*********************************************************************
  *             wscanf (MSVCRT.@)
  */
-int wscanf(const wchar_t *format, ...)
+int CDECL wscanf(const wchar_t *format, ...)
 {
     va_list valist;
     int res;
 
     va_start(valist, format);
-    res = vfwscanf(stdin, format, valist);
+    res = vfwscanf_l(stdin, format, NULL, valist);
     va_end(valist);
     return res;
 }
-#endif
+#endif /* !_LIBCNT_ */
 
 
 /*********************************************************************
  *             sscanf (MSVCRT.@)
  */
-int sscanf(const char *str, const char *format, ...)
+int CDECL sscanf(const char *str, const char *format, ...)
 {
     va_list valist;
     int res;
 
     va_start(valist, format);
-    res = vsscanf(str, format, valist);
+    res = vsscanf_l(str, format, NULL, valist);
     va_end(valist);
     return res;
 }
@@ -172,7 +179,7 @@ int CDECL swscanf(const wchar_t *str, const wchar_t *format, ...)
     int res;
 
     va_start(valist, format);
-    res = vswscanf(str, format, valist);
+    res = vswscanf_l(str, format, NULL, valist);
     va_end(valist);
     return res;
 }
@@ -187,7 +194,7 @@ int CDECL _cscanf(const char *format, ...)
     int res;
 
     va_start(valist, format);
-    res = vcscanf(format, valist);
+    res = vcscanf_l(format, NULL, valist);
     va_end(valist);
     return res;
 }
index 4aada82..cb37ed9 100644 (file)
 #ifdef CONSOLE
 #define _GETC_(file) (consumed++, _getch())
 #define _UNGETC_(nch, file) do { _ungetch(nch); consumed--; } while(0)
-#define _FUNCTION_ int vcscanf(const char *format, va_list ap)
+#ifdef SECURE
+#define _FUNCTION_ static int vcscanf_s_l(const char *format, _locale_t locale, __ms_va_list ap)
+#else  /* SECURE */
+#define _FUNCTION_ static int vcscanf_l(const char *format, _locale_t locale, __ms_va_list ap)
+#endif /* SECURE */
 #else
 #ifdef STRING
 #undef _EOF_
 #define _GETC_(file) (consumed++, *file++)
 #define _UNGETC_(nch, file) do { file--; consumed--; } while(0)
 #ifdef WIDE_SCANF
-#define _FUNCTION_ int vswscanf(const wchar_t *file, const wchar_t *format, va_list ap)
+#ifdef SECURE
+#define _FUNCTION_ static int vswscanf_s_l(const wchar_t *file, const wchar_t *format, _locale_t locale, __ms_va_list ap)
+#else  /* SECURE */
+#define _FUNCTION_ static int vswscanf_l(const wchar_t *file, const wchar_t *format, _locale_t locale, __ms_va_list ap)
+#endif /* SECURE */
 #else /* WIDE_SCANF */
-#define _FUNCTION_ int vsscanf(const char *file, const char *format, va_list ap)
+#ifdef SECURE
+#define _FUNCTION_ static int vsscanf_s_l(const char *file, const char *format, _locale_t locale, __ms_va_list ap)
+#else  /* SECURE */
+#define _FUNCTION_ static int vsscanf_l(const char *file, const char *format, _locale_t locale, __ms_va_list ap)
+#endif /* SECURE */
 #endif /* WIDE_SCANF */
 #else /* STRING */
 #ifdef WIDE_SCANF
 #define _GETC_(file) (consumed++, fgetwc(file))
 #define _UNGETC_(nch, file) do { ungetwc(nch, file); consumed--; } while(0)
-#define _FUNCTION_ int vfwscanf(FILE* file, const wchar_t *format, va_list ap)
+#ifdef SECURE
+#define _FUNCTION_ static int vfwscanf_s_l(FILE* file, const wchar_t *format, _locale_t locale, __ms_va_list ap)
+#else  /* SECURE */
+#define _FUNCTION_ static int vfwscanf_l(FILE* file, const wchar_t *format, _locale_t locale, __ms_va_list ap)
+#endif /* SECURE */
 #else /* WIDE_SCANF */
 #define _GETC_(file) (consumed++, fgetc(file))
 #define _UNGETC_(nch, file) do { ungetc(nch, file); consumed--; } while(0)
-#define _FUNCTION_ int vfscanf(FILE* file, const char *format, va_list ap)
+#ifdef SECURE
+#define _FUNCTION_ static int vfscanf_s_l(FILE* file, const char *format, _locale_t locale, __ms_va_list ap)
+#else  /* SECURE */
+#define _FUNCTION_ static int vfscanf_l(FILE* file, const char *format, _locale_t locale, __ms_va_list ap)
+#endif /* SECURE */
 #endif /* WIDE_SCANF */
 #endif /* STRING */
 #endif /* CONSOLE */
 
 _FUNCTION_ {
+    pthreadlocinfo locinfo;
     int rd = 0, consumed = 0;
     int nch;
     if (!*format) return 0;
@@ -94,6 +115,11 @@ _FUNCTION_ {
         return _EOF_RET;
     }
 
+    if(!locale)
+        locinfo = get_locinfo();
+    else
+        locinfo = locale->locinfo;
+
     while (*format) {
        /* a whitespace character in the format string causes scanf to read,
         * but not store, all consecutive white-space characters in the input
@@ -246,8 +272,12 @@ _FUNCTION_ {
             case 'f':
             case 'g':
             case 'G': { /* read a float */
-                    long double cur = 0;
-                   int negative = 0;
+                    //long double cur = 1, expcnt = 10;
+                    ULONGLONG d, hlp;
+                    int exp = 0, negative = 0;
+                    //unsigned fpcontrol;
+                    //BOOL negexp;
+
                     /* skip initial whitespace */
                     while ((nch!=_EOF_) && _ISSPACE_(nch))
                         nch = _GETC_(file);
@@ -259,69 +289,112 @@ _FUNCTION_ {
                         if (width==0) break;
                         nch = _GETC_(file);
                     }
-                   /* get first digit. */
-                   if ('.' != nch) {
-                     if (!_ISDIGIT_(nch)) break;
-                     cur = (nch - '0');
-                     nch = _GETC_(file);
-                     if (width>0) width--;
-                     /* read until no more digits */
-                     while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
-                        cur = cur*10 + (nch - '0');
+
+                    /* get first digit. */
+                    if (*locinfo->lconv->decimal_point != nch) {
+                        if (!_ISDIGIT_(nch)) break;
+                        d = nch - '0';
                         nch = _GETC_(file);
-                       if (width>0) width--;
-                     }
-                   } else {
-                     cur = 0; /* MaxPayneDemo Fix: .8 -> 0.8 */
-                   }
-                   /* handle decimals */
-                    if (width!=0 && nch == '.') {
-                        long double dec = 1;
+                        if (width>0) width--;
+                        /* read until no more digits */
+                        while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
+                            hlp = d*10 + nch - '0';
+                            nch = _GETC_(file);
+                            if (width>0) width--;
+                            if(d > (ULONGLONG)-1/10 || hlp<d) {
+                                exp++;
+                                break;
+                            }
+                            else
+                                d = hlp;
+                        }
+                        while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
+                            exp++;
+                            nch = _GETC_(file);
+                            if (width>0) width--;
+                        }
+                    } else {
+                        d = 0; /* Fix: .8 -> 0.8 */
+                    }
+
+                    /* handle decimals */
+                    if (width!=0 && nch == *locinfo->lconv->decimal_point) {
                         nch = _GETC_(file);
                         if (width>0) width--;
+
+                        while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
+                            hlp = d*10 + nch - '0';
+                            nch = _GETC_(file);
+                            if (width>0) width--;
+                            if(d > (ULONGLONG)-1/10 || hlp<d)
+                                break;
+
+                            d = hlp;
+                            exp--;
+                        }
                         while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
-                            dec /= 10;
-                            cur += dec * (nch - '0');
                             nch = _GETC_(file);
                             if (width>0) width--;
                         }
                     }
-                   /* handle exponent */
-                   if (width!=0 && (nch == 'e' || nch == 'E')) {
-                       int exponent = 0, negexp = 0;
-                       double expcnt, shift;
+
+                    /* handle exponent */
+                    if (width!=0 && (nch == 'e' || nch == 'E')) {
+                        int sign = 1, e = 0;
+
                         nch = _GETC_(file);
                         if (width>0) width--;
-                       /* possible sign on the exponent */
-                       if (width!=0 && (nch=='+' || nch=='-')) {
-                           negexp = (nch=='-');
+                        if (width!=0 && (nch=='+' || nch=='-')) {
+                            if(nch == '-')
+                                sign = -1;
                             nch = _GETC_(file);
                             if (width>0) width--;
-                       }
-                       /* exponent digits */
-                       while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
-                           exponent *= 10;
-                           exponent += (nch - '0');
+                        }
+
+                        /* exponent digits */
+                        while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
+                            if(e > INT_MAX/10 || (e = e*10 + nch - '0')<0)
+                                e = INT_MAX;
                             nch = _GETC_(file);
                             if (width>0) width--;
                         }
-                       /* update 'cur' with this exponent. */
-                       expcnt = 10;
-                       shift = 1.0;
-                       while (exponent!=0) {
-                           if (exponent&1)
-                               shift *= expcnt;
-                           exponent/=2;
-                           expcnt=expcnt*expcnt;
-                       }
-                       cur = (negexp ? cur / shift : cur * shift);
-                   }
+                        e *= sign;
+
+                        if(exp<0 && e<0 && e+exp>0) exp = INT_MIN;
+                        else if(exp>0 && e>0 && e+exp<0) exp = INT_MAX;
+                        else exp += e;
+                    }
+
+#ifdef __REACTOS__
+                    /* ReactOS: don't inline float processing (kernel/freeldr don't like that! */
+                    _internal_handle_float(negative, exp, suppress, d, l_prefix || L_prefix, &ap);
+                    st = 1;
+#else
+                    fpcontrol = _control87(0, 0);
+                    _control87(MSVCRT__EM_DENORMAL|MSVCRT__EM_INVALID|MSVCRT__EM_ZERODIVIDE
+                            |MSVCRT__EM_OVERFLOW|MSVCRT__EM_UNDERFLOW|MSVCRT__EM_INEXACT, 0xffffffff);
+
+                    negexp = (exp < 0);
+                    if(negexp)
+                        exp = -exp;
+                    /* update 'cur' with this exponent. */
+                    while(exp) {
+                        if(exp & 1)
+                            cur *= expcnt;
+                        exp /= 2;
+                        expcnt = expcnt*expcnt;
+                    }
+                    cur = (negexp ? d/cur : d*cur);
+
+                    _control87(fpcontrol, 0xffffffff);
+
                     st = 1;
                     if (!suppress) {
-                       if (L_prefix) _SET_NUMBER_(long double);
+                        if (L_prefix) _SET_NUMBER_(double);
                         else if (l_prefix) _SET_NUMBER_(double);
                         else _SET_NUMBER_(float);
                     }
+#endif /* __REACTOS__ */
                 }
                 break;
                /* According to msdn,
@@ -448,11 +521,7 @@ _FUNCTION_ {
                    int invert = 0; /* Set if we are NOT to find the chars */
 
             /* Init our bitmap */
-#ifdef _LIBCNT_
-            Mask = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, _BITMAPSIZE_/8);
-#else
             Mask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _BITMAPSIZE_/8);
-#endif
             RtlInitializeBitMap(&bitMask, Mask, _BITMAPSIZE_);
 
                    /* Read the format */
@@ -497,11 +566,7 @@ _FUNCTION_ {
                     }
                     /* terminate */
                     if (!suppress) *sptr = 0;
-#ifdef _LIBCNT_
-                    RtlFreeHeap(RtlGetProcessHeap(), 0, Mask);
-#else
                     HeapFree(GetProcessHeap(), 0, Mask);
-#endif
                 }
                 break;
             default:
diff --git a/reactos/lib/sdk/crt/string/winesup.c b/reactos/lib/sdk/crt/string/winesup.c
new file mode 100644 (file)
index 0000000..860fe85
--- /dev/null
@@ -0,0 +1,102 @@
+
+#include "precomp.h"
+#include "winesup.h"
+
+#ifdef _LIBCNT_
+
+static struct lconv _LIBCNT_lconv =
+{
+    ".", // char* decimal_point;
+    ",", // char* thousands_sep;
+    " ", // char* grouping;
+    "$", // char* int_curr_symbol;
+    "$", // char* currency_symbol;
+    ".", // char* mon_decimal_point;
+    "?", // char* mon_thousands_sep;
+    "/", // char* mon_grouping;
+    "+", // char* positive_sign;
+    "-", // char* negative_sign;
+    4, // char int_frac_digits;
+    4, // char frac_digits;
+    4, // char p_cs_precedes;
+    1, // char p_sep_by_space;
+    0, // char n_cs_precedes;
+    1, // char n_sep_by_space;
+    1, // char p_sign_posn;
+    1, // char n_sign_posn;
+};
+
+threadlocinfo _LIBCNT_locinfo =
+{
+    2, // LONG refcount;
+    0, // CP_ACP, // unsigned int lc_codepage;
+    0, // unsigned int lc_collate_cp;
+    {0}, // unsigned long lc_handle[6];
+    {{0}}, // LC_ID lc_id[6];
+
+    // struct {
+    // char *locale;
+    // wchar_t *wlocale;
+    // int *refcount;
+    // int *wrefcount;
+    // } lc_category[6];
+    {{0}},
+
+    0, // int lc_clike;
+    2, // int mb_cur_max;
+    0, // int *lconv_intl_refcount;
+    0, // int *lconv_num_refcount;
+    0, // int *lconv_mon_refcount;
+    &_LIBCNT_lconv, // struct MSVCRT_lconv *lconv;
+    0, // int *ctype1_refcount;
+    0, // unsigned short *ctype1;
+    0, // const unsigned short *pctype;
+    0, // unsigned char *pclmap;
+    0, // unsigned char *pcumap;
+    0, // struct __lc_time_data *lc_time_curr;
+};
+
+#define get_locinfo() (&_LIBCNT_locinfo)
+
+#endif
+
+#define _SET_NUMBER_(type) *va_arg((*ap), type*) = negative ? -cur : cur
+
+void
+__declspec(noinline)
+_internal_handle_float(
+    int negative,
+    int exp,
+    int suppress,
+    ULONGLONG d,
+    int l_or_L_prefix,
+    va_list *ap)
+{
+    long double cur = 1, expcnt = 10;
+    unsigned fpcontrol;
+    BOOL negexp;
+
+    fpcontrol = _control87(0, 0);
+    _control87(_EM_DENORMAL|_EM_INVALID|_EM_ZERODIVIDE
+            |_EM_OVERFLOW|_EM_UNDERFLOW|_EM_INEXACT, 0xffffffff);
+
+    negexp = (exp < 0);
+    if(negexp)
+        exp = -exp;
+    /* update 'cur' with this exponent. */
+    while(exp) {
+        if(exp & 1)
+            cur *= expcnt;
+        exp /= 2;
+        expcnt = expcnt*expcnt;
+    }
+    cur = (negexp ? d/cur : d*cur);
+
+    _control87(fpcontrol, 0xffffffff);
+
+    if (!suppress) {
+        if (l_or_L_prefix) _SET_NUMBER_(double);
+        else _SET_NUMBER_(float);
+    }
+}
+#undef _SET_NUMBER_
diff --git a/reactos/lib/sdk/crt/string/winesup.h b/reactos/lib/sdk/crt/string/winesup.h
new file mode 100644 (file)
index 0000000..7bc3ed7
--- /dev/null
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <stdio.h>
+#include <conio.h>
+#include <float.h>
+#include <locale.h>
+#include <internal/locale.h>
+
+#undef NtCurrentPeb
+#define NtCurrentPeb() (NtCurrentTeb()->Peb)
+#define GetProcessHeap() (NtCurrentPeb()->ProcessHeap)
+
+#define HeapAlloc(_Heap, _Flags, _Size) RtlAllocateHeap(_Heap, _Flags, _Size)
+#define HeapFree(_Heap, _Flags, _Ptr) RtlFreeHeap(_Heap, _Flags, _Ptr)
+
+#ifdef _LIBCNT_
+static inline unsigned int __control87(unsigned int new, unsigned int mask)
+{
+    return 0;
+}
+#define _control87 __control87
+extern threadlocinfo _LIBCNT_locinfo;
+#define get_locinfo() (&_LIBCNT_locinfo)
+#else
+#define get_locinfo() ((pthreadlocinfo)get_locinfo())
+#endif
+
+void
+__declspec(noinline)
+_internal_handle_float(
+    int negative,
+    int exp,
+    int suppress,
+    ULONGLONG d,
+    int l_or_L_prefix,
+    va_list *ap);
+
+//#include <debug.h>
+
+#define __WINE_DEBUG_H
+#undef WINE_DEFAULT_DEBUG_CHANNEL
+#define WINE_DEFAULT_DEBUG_CHANNEL(_Ch)
+#undef TRACE
+#define TRACE(...) /* DPRINT(__VA_ARGS__) */
+#define debugstr_a(format) format