summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2013-10-15 12:17:46 +0200
committerEike Rathke <erack@redhat.com>2013-10-15 12:52:15 +0200
commit66a96c82746118c70a447d7768b0428e15d2f5ad (patch)
tree9b03b73ed296e7f1cc8de39e57f84bc41f794011
parentf85c494b53fc7c9472689a6d94de5f3e185c376e (diff)
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
-rw-r--r--basic/qa/cppunit/test_scanner.cxx29
-rw-r--r--basic/source/comp/scanner.cxx96
2 files changed, 74 insertions, 51 deletions
diff --git a/basic/qa/cppunit/test_scanner.cxx b/basic/qa/cppunit/test_scanner.cxx
index acf740fb03a1..b19e52eeffa8 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 d966406b4f42..0a5a4932f99f 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 );