basic/qa/cppunit/test_compiler_checks.cxx | 53 ++++++++++++++++++++++++++++++ basic/source/comp/scanner.cxx | 37 ++++++++++++++++---- 2 files changed, 83 insertions(+), 7 deletions(-)
New commits: commit a400c865a6c9f0185a1986db617ee6fc9dd1861d Author: Luv Sharma <luvsharma....@gmail.com> AuthorDate: Sat Jan 27 14:54:49 2024 +0530 Commit: Andreas Heinisch <andreas.heini...@yahoo.de> CommitDate: Mon Apr 22 16:05:53 2024 +0200 tdf#93727 Syntax Error on # in basic Change-Id: I400a4061de580a5c91b0e4763cad40ae88a9f738 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162639 Tested-by: Jenkins Tested-by: Andreas Heinisch <andreas.heini...@yahoo.de> Reviewed-by: Andreas Heinisch <andreas.heini...@yahoo.de> diff --git a/basic/qa/cppunit/test_compiler_checks.cxx b/basic/qa/cppunit/test_compiler_checks.cxx index 773719e9fd45..2b8e72997c64 100644 --- a/basic/qa/cppunit/test_compiler_checks.cxx +++ b/basic/qa/cppunit/test_compiler_checks.cxx @@ -114,4 +114,57 @@ CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf149402_vba) CPPUNIT_ASSERT(!aMacro.HasError()); } +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf93727_if) +{ + // #If and #End directive + MacroSnippet aMacro("Sub doUnitTest " + " #If 1 = 1 Then " + " Const a = 10 " + " #End If " + "End Sub "); + aMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("#If directive causes compile error", !aMacro.HasError()); +} + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf93727_else) +{ + // #Else directive + MacroSnippet aMacro("Sub doUnitTest " + "a = 0 " + "#If 1 = 0 Then " + " a = 10 " + "#Else " + " a = 20 " + "#End If " + "End Sub "); + aMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("#Else directive causes compile error", !aMacro.HasError()); +} + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf93727_elseif) +{ + // #ElseIf directive + MacroSnippet aMacro("Sub doUnitTest " + "a = 0 " + " #If 1 = 0 Then " + " a = 10 " + " #ElseIf 2 = 2 Then " + " a = 20 " + " #End If " + "End Sub "); + aMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("#ElseIf directive causes compile error", !aMacro.HasError()); +} + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf93727_const) +{ + // #Const directive + MacroSnippet aMacro("#Const MaxValue = 1000 " + "Sub doUnitTest " + " Dim value As Integer " + " value = MaxValue " + "End Sub "); + aMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("#Const directive causes compile error", !aMacro.HasError()); +} /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/basic/source/comp/scanner.cxx b/basic/source/comp/scanner.cxx index 45b65a29b129..820951889ad7 100644 --- a/basic/source/comp/scanner.cxx +++ b/basic/source/comp/scanner.cxx @@ -29,6 +29,7 @@ #include <rtl/character.hxx> #include <o3tl/string_view.hxx> #include <utility> +#include <vector> SbiScanner::SbiScanner(OUString _aBuf, StarBASIC* p) : aBuf(std::move(_aBuf)) @@ -209,6 +210,17 @@ bool SbiScanner::readLine() return true; } +// Function to check if a string is a valid compiler directive +static bool isValidCompilerDirective(std::u16string_view directive) { + static const std::vector<std::u16string_view> validDirectives = { + u"if", u"elseif", u"else", u"end", u"const" + }; + + return std::any_of(validDirectives.begin(), validDirectives.end(), [&](const auto& valid) { + return o3tl::matchIgnoreAsciiCase(directive, valid); + }); +} + bool SbiScanner::NextSym() { // memorize for the EOLN-case @@ -220,7 +232,6 @@ bool SbiScanner::NextSym() eScanType = SbxVARIANT; aSym.clear(); bHash = bSymbol = bNumber = bSpaces = false; - bool bCompilerDirective = false; // read in line? if (nLineIdx == -1) @@ -256,6 +267,8 @@ bool SbiScanner::NextSym() if(nCol < aLine.getLength() && aLine[nCol] == '#') { sal_Int32 nLineTempIdx = nLineIdx; + std::u16string_view candidate(aLine.subView(nCol + 1)); + do { nLineTempIdx++; @@ -266,9 +279,20 @@ bool SbiScanner::NextSym() { ++nLineIdx; ++nCol; - //ignore compiler directives (# is first non-space character) + //handle compiler directives (# is first non-space character) if (nOldCol2 == 0) - bCompilerDirective = true; + { + if (isValidCompilerDirective(candidate)) + { + // Skip the whole line if starts with a hash and is a valid compiler directive + nCol = 0; + goto eoln; + } + else + { + GenError(ERRCODE_BASIC_SYNTAX); + } + } else bHash = true; } @@ -660,10 +684,9 @@ bool SbiScanner::NextSym() PrevLineCommentLbl: - if( bPrevLineExtentsComment || (eScanType != SbxSTRING && - ( bCompilerDirective || - aSym.startsWith("'") || - aSym.equalsIgnoreAsciiCase( "REM" ) ) ) ) + if (bPrevLineExtentsComment || + (eScanType != SbxSTRING && + (aSym.startsWith("'") || aSym.equalsIgnoreAsciiCase("REM") || aSym.startsWith("#")))) { bPrevLineExtentsComment = false; aSym = "REM";