basic/qa/cppunit/test_scanner.cxx |   29 ++++++-----
 basic/source/comp/scanner.cxx     |   96 ++++++++++++++++++++++----------------
 2 files changed, 74 insertions(+), 51 deletions(-)

New commits:
commit 66a96c82746118c70a447d7768b0428e15d2f5ad
Author: Eike Rathke <er...@redhat.com>
Date:   Tue Oct 15 12:17:46 2013 +0200

    clean up SbiScanner::NextSym() a little, fdo#70319 follow-up
    
    Number recognition was suboptimal and didn't properly resync scan
    positions after having detected an error.
    
    Change-Id: I278fdaaf17ed40560785deaaad0e3412a249d90a

diff --git a/basic/qa/cppunit/test_scanner.cxx 
b/basic/qa/cppunit/test_scanner.cxx
index acf740fb..b19e52e 100644
--- a/basic/qa/cppunit/test_scanner.cxx
+++ b/basic/qa/cppunit/test_scanner.cxx
@@ -576,10 +576,12 @@ namespace
     CPPUNIT_ASSERT(errors == 0);
 
     symbols = getSymbols(source2, errors);
-    CPPUNIT_ASSERT(symbols.size() == 2);
-    CPPUNIT_ASSERT(symbols[0].number == 1.23);
+    CPPUNIT_ASSERT(symbols.size() == 3);
+    CPPUNIT_ASSERT(symbols[0].number == 1.2);
     CPPUNIT_ASSERT(symbols[0].type == SbxDOUBLE);
-    CPPUNIT_ASSERT(symbols[1].text == cr);
+    CPPUNIT_ASSERT(rtl::math::round( symbols[1].number, 12) == 
rtl::math::round( .3, 12));
+    CPPUNIT_ASSERT(symbols[1].type == SbxDOUBLE);
+    CPPUNIT_ASSERT(symbols[2].text == cr);
     CPPUNIT_ASSERT(errors == 1);
 
     symbols = getSymbols(source3, errors);
@@ -627,10 +629,11 @@ namespace
     CPPUNIT_ASSERT(errors == 0);
 
     symbols = getSymbols(source9, errors);
-    CPPUNIT_ASSERT(symbols.size() == 2);
-    CPPUNIT_ASSERT(symbols[0].number == 12000);
+    CPPUNIT_ASSERT(symbols.size() == 3);
+    CPPUNIT_ASSERT(symbols[0].number == 12);
     CPPUNIT_ASSERT(symbols[0].type == SbxDOUBLE);
-    CPPUNIT_ASSERT(symbols[1].text == cr);
+    CPPUNIT_ASSERT(symbols[1].text == OUString("dE3"));
+    CPPUNIT_ASSERT(symbols[2].text == cr);
     CPPUNIT_ASSERT(errors == 1);
 
     symbols = getSymbols(source10, errors);
@@ -647,16 +650,16 @@ namespace
     CPPUNIT_ASSERT(symbols[1].text == cr);
     CPPUNIT_ASSERT(errors == 0);
 
-    /* FIXME: SbiScanner::NextSym() is total crap, the result of scanning
-     * "12e++3" should be something different than this.. */
     symbols = getSymbols(source12, errors);
-    CPPUNIT_ASSERT(symbols.size() == 4);
+    CPPUNIT_ASSERT(symbols.size() == 6);
     CPPUNIT_ASSERT(symbols[0].number == 12);
     CPPUNIT_ASSERT(symbols[0].type == SbxDOUBLE);
-    CPPUNIT_ASSERT(symbols[1].text == OUString("+"));
-    CPPUNIT_ASSERT(symbols[2].number == 3);
-    CPPUNIT_ASSERT(symbols[2].type == SbxINTEGER);
-    CPPUNIT_ASSERT(symbols[3].text == cr);
+    CPPUNIT_ASSERT(symbols[1].text == OUString("e"));
+    CPPUNIT_ASSERT(symbols[2].text == OUString("+"));
+    CPPUNIT_ASSERT(symbols[3].text == OUString("+"));
+    CPPUNIT_ASSERT(symbols[4].number == 3);
+    CPPUNIT_ASSERT(symbols[4].type == SbxINTEGER);
+    CPPUNIT_ASSERT(symbols[5].text == cr);
     CPPUNIT_ASSERT(errors == 1);
 
     symbols = getSymbols(source13, errors);
diff --git a/basic/source/comp/scanner.cxx b/basic/source/comp/scanner.cxx
index d966406..0a5a493 100644
--- a/basic/source/comp/scanner.cxx
+++ b/basic/source/comp/scanner.cxx
@@ -302,12 +302,12 @@ bool SbiScanner::NextSym()
             (nCol + 1 < aLine.getLength() && aLine[nCol] == '.' && 
theBasicCharClass::get().isDigit(aLine[nCol + 1] & 0xFF)))
     {
         short exp = 0;
-        short comma = 0;
-        short ndig = 0;
-        short ncdig = 0;
+        short dec = 0;
         eScanType = SbxDOUBLE;
+        bool bScanError = false;
         bool bBufOverflow = false;
-        while(nCol < aLine.getLength() && strchr("0123456789.DEde", 
aLine[nCol]))
+        // All this because of 'D' or 'd' floating point type, sigh..
+        while(!bScanError && nCol < aLine.getLength() && 
strchr("0123456789.DEde", aLine[nCol]))
         {
             // from 4.1.1996: buffer full? -> go on scanning empty
             if( (p-buf) == (BUF_SIZE-1) )
@@ -319,64 +319,84 @@ bool SbiScanner::NextSym()
             // point or exponent?
             if(aLine[nCol] == '.')
             {
-                if( ++comma > 1 )
-                {
-                    ++pLine; ++nCol; continue;
-                }
+                if( ++dec > 1 )
+                    bScanError = true;
                 else
-                {
-                    *p = '.';
-                    ++p, ++pLine, ++nCol;
-                }
+                    *p++ = '.';
             }
             else if(strchr("DdEe", aLine[nCol]))
             {
                 if (++exp > 1)
+                    bScanError = true;
+                else
                 {
-                    ++pLine; ++nCol; continue;
-                }
-
-                *p = 'E';
-                ++p, ++pLine, ++nCol;
-
-                if(aLine[nCol] == '+')
-                    ++pLine, ++nCol;
-                else if(aLine[nCol] == '-')
-                {
-                    *p = '-';
-                    ++p, ++pLine, ++nCol;
+                    *p++ = 'E';
+                    if (nCol + 1 < aLine.getLength() && (aLine[nCol+1] == '+' 
|| aLine[nCol+1] == '-'))
+                    {
+                        ++pLine, ++nCol;
+                        if( (p-buf) == (BUF_SIZE-1) )
+                        {
+                            bBufOverflow = true;
+                            continue;
+                        }
+                        *p++ = aLine[nCol];
+                    }
                 }
             }
             else
             {
-                *p = aLine[nCol];
-                ++p, ++pLine, ++nCol;
-                if( comma && !exp ) ++ncdig;
+                *p++ = aLine[nCol];
             }
-            if (!exp) ++ndig;
+            ++pLine, ++nCol;
         }
         *p = 0;
         aSym = p; bNumber = true;
 
-        if( comma > 1 || exp > 1 )
-        {   aError = OUString('.');
-            GenError( SbERR_BAD_CHAR_IN_NUMBER );   }
+        // For bad characters, scan and parse errors generate only one error.
+        SbError nError = 0;
+        if (bScanError)
+        {
+            --pLine, --nCol;
+            aError = OUString( aLine[nCol]);
+            nError = SbERR_BAD_CHAR_IN_NUMBER;
+        }
 
         rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
         const sal_Unicode* pParseEnd = buf;
         nVal = rtl_math_uStringToDouble( buf, buf+(p-buf), '.', ',', &eStatus, 
&pParseEnd );
-        if (eStatus != rtl_math_ConversionStatus_Ok || pParseEnd != 
buf+(p-buf))
-            GenError( SbERR_MATH_OVERFLOW );
+        if (pParseEnd != buf+(p-buf))
+        {
+            // e.g. "12e" or "12e+", or with bScanError "12d"+"E".
+            sal_Int32 nChars = buf+(p-buf) - pParseEnd;
+            pLine -= nChars;
+            nCol -= nChars;
+            // For bScanError, pLine and nCol were already decremented, just
+            // add that character to the parse end.
+            if (bScanError)
+                ++nChars;
+            // Copy error position from original string, not the buffer
+            // replacement where "12dE" => "12EE".
+            aError = aLine.copy( nCol, nChars);
+            nError = SbERR_BAD_CHAR_IN_NUMBER;
+        }
+        else if (eStatus != rtl_math_ConversionStatus_Ok)
+        {
+            // Keep the scan error and character at position, if any.
+            if (!nError)
+                nError = SbERR_MATH_OVERFLOW;
+        }
+
+        if (nError)
+            GenError( nError );
 
-        ndig = ndig - comma;
-        if( !comma && !exp )
+        if( !dec && !exp )
         {
             if( nVal >= SbxMININT && nVal <= SbxMAXINT )
                 eScanType = SbxINTEGER;
-            else
-            if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
-                eScanType = SbxLONG;
+            else if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
+                    eScanType = SbxLONG;
         }
+
         if( bBufOverflow )
             GenError( SbERR_MATH_OVERFLOW );
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to