LCOV - code coverage report
Current view: top level - basic/source/sbx - sbxexec.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 56 190 29.5 %
Date: 2015-06-13 12:38:46 Functions: 5 10 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <tools/errcode.hxx>
      21             : #include <vcl/svapp.hxx>
      22             : #include <basic/sbx.hxx>
      23             : #include <rtl/character.hxx>
      24             : 
      25             : 
      26             : static SbxVariable* Element
      27             :     ( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf,
      28             :       SbxClassType );
      29             : 
      30          90 : static const sal_Unicode* SkipWhitespace( const sal_Unicode* p )
      31             : {
      32         180 :     while( *p && ( *p == ' ' || *p == '\t' ) )
      33           0 :         p++;
      34          90 :     return p;
      35             : }
      36             : 
      37             : // Scanning of a symbol. The symbol were inserted in rSym, the return value
      38             : // is the new scan position. The symbol is at errors empty.
      39             : 
      40          36 : static const sal_Unicode* Symbol( const sal_Unicode* p, OUString& rSym )
      41             : {
      42          36 :     sal_uInt16 nLen = 0;
      43             :     // Did we have a nonstandard symbol?
      44          36 :     if( *p == '[' )
      45             :     {
      46           0 :         rSym = ++p;
      47           0 :         while( *p && *p != ']' )
      48             :         {
      49           0 :             p++, nLen++;
      50             :         }
      51           0 :         p++;
      52             :     }
      53             :     else
      54             :     {
      55             :         // A symbol had to begin with a alphabetic character or an underline
      56          36 :         if( !rtl::isAsciiAlpha( *p ) && *p != '_' )
      57             :         {
      58           0 :             SbxBase::SetError( SbxERR_SYNTAX );
      59             :         }
      60             :         else
      61             :         {
      62          36 :             rSym = p;
      63             :             // The it can contain alphabetic characters, numbers or underlines
      64         636 :             while( *p && (rtl::isAsciiAlphanumeric( *p ) || *p == '_') )
      65             :             {
      66         564 :                 p++, nLen++;
      67             :             }
      68             :             // BASIC-Standard-Suffixes were ignored
      69          36 :             if( *p && (*p == '%' || *p == '&' || *p == '!' || *p == '#' || *p == '$' ) )
      70             :             {
      71           0 :                 p++;
      72             :             }
      73             :         }
      74             :     }
      75          36 :     rSym = rSym.copy( 0, nLen );
      76          36 :     return p;
      77             : }
      78             : 
      79             : // Qualified name. Element.Element....
      80             : 
      81          18 : static SbxVariable* QualifiedName
      82             :     ( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf, SbxClassType t )
      83             : {
      84             : 
      85          18 :     SbxVariableRef refVar;
      86          18 :     const sal_Unicode* p = SkipWhitespace( *ppBuf );
      87          18 :     if( rtl::isAsciiAlpha( *p ) || *p == '_' || *p == '[' )
      88             :     {
      89             :         // Read in the element
      90          18 :         refVar = Element( pObj, pGbl, &p, t );
      91          54 :         while( refVar.Is() && (*p == '.' || *p == '!') )
      92             :         {
      93             :             // It follows still an objectelement. The current element
      94             :             // had to be a SBX-Object or had to deliver such an object!
      95          18 :             pObj = PTR_CAST(SbxObject,static_cast<SbxVariable*>(refVar));
      96          18 :             if( !pObj )
      97             :                 // Then it had to deliver an object
      98           0 :                 pObj = PTR_CAST(SbxObject,refVar->GetObject());
      99          18 :             refVar.Clear();
     100          18 :             if( !pObj )
     101           0 :                 break;
     102          18 :             p++;
     103             :             // And the next element please
     104          18 :             refVar = Element( pObj, pGbl, &p, t );
     105             :         }
     106             :     }
     107             :     else
     108           0 :         SbxBase::SetError( SbxERR_SYNTAX );
     109          18 :     *ppBuf = p;
     110          18 :     if( refVar.Is() )
     111          18 :         refVar->AddFirstRef();
     112          18 :     return refVar;
     113             : }
     114             : 
     115             : // Read in of an operand. This could be a number, a string or
     116             : // a function (with optional parameters).
     117             : 
     118           0 : static SbxVariable* Operand
     119             :     ( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf, bool bVar )
     120             : {
     121           0 :     SbxVariableRef refVar( new SbxVariable );
     122           0 :     const sal_Unicode* p = SkipWhitespace( *ppBuf );
     123           0 :     if( !bVar && ( rtl::isAsciiDigit( *p )
     124           0 :                    || ( *p == '.' && rtl::isAsciiDigit( *( p+1 ) ) )
     125           0 :                    || *p == '-'
     126           0 :                    || *p == '&' ) )
     127             :     {
     128             :         // A number could be scanned in directly!
     129             :         sal_uInt16 nLen;
     130           0 :         if( !refVar->Scan( OUString( p ), &nLen ) )
     131             :         {
     132           0 :             refVar.Clear();
     133             :         }
     134             :         else
     135             :         {
     136           0 :             p += nLen;
     137             :         }
     138             :     }
     139           0 :     else if( !bVar && *p == '"' )
     140             :     {
     141             :         // A string
     142           0 :         OUString aString;
     143           0 :         p++;
     144             :         for( ;; )
     145             :         {
     146             :             // This is perhaps an error
     147           0 :             if( !*p )
     148             :             {
     149           0 :                 return NULL;
     150             :             }
     151             :             // Double quotes are OK
     152           0 :             if( *p == '"' )
     153             :             {
     154           0 :                 if( *++p != '"' )
     155             :                 {
     156           0 :                     break;
     157             :                 }
     158             :             }
     159           0 :             aString += OUString(*p++);
     160             :         }
     161           0 :         refVar->PutString( aString );
     162             :     }
     163             :     else
     164             :     {
     165           0 :         refVar = QualifiedName( pObj, pGbl, &p, SbxCLASS_DONTCARE );
     166             :     }
     167           0 :     *ppBuf = p;
     168           0 :     if( refVar.Is() )
     169           0 :         refVar->AddFirstRef();
     170           0 :     return refVar;
     171             : }
     172             : 
     173             : // Read in of a simple term. The operands +, -, * and /
     174             : // are supported.
     175             : 
     176           0 : static SbxVariable* MulDiv( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf )
     177             : {
     178           0 :     const sal_Unicode* p = *ppBuf;
     179           0 :     SbxVariableRef refVar( Operand( pObj, pGbl, &p, false ) );
     180           0 :     p = SkipWhitespace( p );
     181           0 :     while( refVar.Is() && ( *p == '*' || *p == '/' ) )
     182             :     {
     183           0 :         sal_Unicode cOp = *p++;
     184           0 :         SbxVariableRef refVar2( Operand( pObj, pGbl, &p, false ) );
     185           0 :         if( refVar2.Is() )
     186             :         {
     187             :             // temporary variable!
     188           0 :             SbxVariable* pVar = refVar;
     189           0 :             pVar = new SbxVariable( *pVar );
     190           0 :             refVar = pVar;
     191           0 :             if( cOp == '*' )
     192           0 :                 *refVar *= *refVar2;
     193             :             else
     194           0 :                 *refVar /= *refVar2;
     195             :         }
     196             :         else
     197             :         {
     198           0 :             refVar.Clear();
     199           0 :             break;
     200             :         }
     201           0 :     }
     202           0 :     *ppBuf = p;
     203           0 :     if( refVar.Is() )
     204           0 :         refVar->AddFirstRef();
     205           0 :     return refVar;
     206             : }
     207             : 
     208           0 : static SbxVariable* PlusMinus( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf )
     209             : {
     210           0 :     const sal_Unicode* p = *ppBuf;
     211           0 :     SbxVariableRef refVar( MulDiv( pObj, pGbl, &p ) );
     212           0 :     p = SkipWhitespace( p );
     213           0 :     while( refVar.Is() && ( *p == '+' || *p == '-' ) )
     214             :     {
     215           0 :         sal_Unicode cOp = *p++;
     216           0 :         SbxVariableRef refVar2( MulDiv( pObj, pGbl, &p ) );
     217           0 :         if( refVar2.Is() )
     218             :         {
     219             :             // temporaere Variable!
     220           0 :             SbxVariable* pVar = refVar;
     221           0 :             pVar = new SbxVariable( *pVar );
     222           0 :             refVar = pVar;
     223           0 :             if( cOp == '+' )
     224           0 :                 *refVar += *refVar2;
     225             :             else
     226           0 :                 *refVar -= *refVar2;
     227             :         }
     228             :         else
     229             :         {
     230           0 :             refVar.Clear();
     231           0 :             break;
     232             :         }
     233           0 :     }
     234           0 :     *ppBuf = p;
     235           0 :     if( refVar.Is() )
     236           0 :         refVar->AddFirstRef();
     237           0 :     return refVar;
     238             : }
     239             : 
     240           0 : static SbxVariable* Assign( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf )
     241             : {
     242           0 :     const sal_Unicode* p = *ppBuf;
     243           0 :     SbxVariableRef refVar( Operand( pObj, pGbl, &p, true ) );
     244           0 :     p = SkipWhitespace( p );
     245           0 :     if( refVar.Is() )
     246             :     {
     247           0 :         if( *p == '=' )
     248             :         {
     249             :             // Assign only onto properties!
     250           0 :             if( refVar->GetClass() != SbxCLASS_PROPERTY )
     251             :             {
     252           0 :                 SbxBase::SetError( SbxERR_BAD_ACTION );
     253           0 :                 refVar.Clear();
     254             :             }
     255             :             else
     256             :             {
     257           0 :                 p++;
     258           0 :                 SbxVariableRef refVar2( PlusMinus( pObj, pGbl, &p ) );
     259           0 :                 if( refVar2.Is() )
     260             :                 {
     261           0 :                     SbxVariable* pVar = refVar;
     262           0 :                     SbxVariable* pVar2 = refVar2;
     263           0 :                     *pVar = *pVar2;
     264           0 :                     pVar->SetParameters( NULL );
     265           0 :                 }
     266             :             }
     267             :         }
     268             :         else
     269             :             // Simple call: once activating
     270           0 :             refVar->Broadcast( SBX_HINT_DATAWANTED );
     271             :     }
     272           0 :     *ppBuf = p;
     273           0 :     if( refVar.Is() )
     274           0 :         refVar->AddFirstRef();
     275           0 :     return refVar;
     276             : }
     277             : 
     278             : // Read in of an element. This is a symbol, optional followed
     279             : // by a parameter list. The symbol will be searched in the
     280             : // specified object and the parameter list will be attached if necessary.
     281             : 
     282          36 : static SbxVariable* Element
     283             :     ( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf,
     284             :       SbxClassType t )
     285             : {
     286          36 :     OUString aSym;
     287          36 :     const sal_Unicode* p = Symbol( *ppBuf, aSym );
     288          72 :     SbxVariableRef refVar;
     289          36 :     if( !aSym.isEmpty() )
     290             :     {
     291          36 :         SbxFlagBits nOld = pObj->GetFlags();
     292          36 :         if( pObj == pGbl )
     293             :         {
     294          18 :             pObj->SetFlag( SBX_GBLSEARCH );
     295             :         }
     296          36 :         refVar = pObj->Find( aSym, t );
     297          36 :         pObj->SetFlags( nOld );
     298          36 :         if( refVar.Is() )
     299             :         {
     300          36 :             refVar->SetParameters( NULL );
     301             :             // Follow still parameter?
     302          36 :             p = SkipWhitespace( p );
     303          36 :             if( *p == '(' )
     304             :             {
     305           0 :                 p++;
     306           0 :                 SbxArrayRef refPar = new SbxArray;
     307           0 :                 sal_uInt16 nArg = 0;
     308             :                 // We are once relaxed and accept as well
     309             :                 // the line- or commandend as delimiter
     310             :                 // Search parameter always global!
     311           0 :                 while( *p && *p != ')' && *p != ']' )
     312             :                 {
     313           0 :                     SbxVariableRef refArg = PlusMinus( pGbl, pGbl, &p );
     314           0 :                     if( !refArg )
     315             :                     {
     316             :                         // Error during the parsing
     317           0 :                         refVar.Clear(); break;
     318             :                     }
     319             :                     else
     320             :                     {
     321             :                         // One copies the parameter, so that
     322             :                         // one have the current status (triggers also
     323             :                         // the call per access)
     324           0 :                         SbxVariable* pArg = refArg;
     325           0 :                         refPar->Put( new SbxVariable( *pArg ), ++nArg );
     326             :                     }
     327           0 :                     p = SkipWhitespace( p );
     328           0 :                     if( *p == ',' )
     329           0 :                         p++;
     330           0 :                 }
     331           0 :                 if( *p == ')' )
     332           0 :                     p++;
     333           0 :                 if( refVar.Is() )
     334           0 :                     refVar->SetParameters( refPar );
     335             :             }
     336             :         }
     337             :         else
     338           0 :             SbxBase::SetError( SbxERR_NO_METHOD );
     339             :     }
     340          36 :     *ppBuf = p;
     341          36 :     if( refVar.Is() )
     342          36 :         refVar->AddFirstRef();
     343          72 :     return refVar;
     344             : }
     345             : 
     346             : // Mainroutine
     347             : 
     348           0 : SbxVariable* SbxObject::Execute( const OUString& rTxt )
     349             : {
     350           0 :     SbxVariable* pVar = NULL;
     351           0 :     const sal_Unicode* p = rTxt.getStr();
     352             :     for( ;; )
     353             :     {
     354           0 :         p = SkipWhitespace( p );
     355           0 :         if( !*p )
     356             :         {
     357           0 :             break;
     358             :         }
     359           0 :         if( *p++ != '[' )
     360             :         {
     361           0 :             SetError( SbxERR_SYNTAX ); break;
     362             :         }
     363           0 :         pVar = Assign( this, this, &p );
     364           0 :         if( !pVar )
     365             :         {
     366           0 :             break;
     367             :         }
     368           0 :         p = SkipWhitespace( p );
     369           0 :         if( *p++ != ']' )
     370             :         {
     371           0 :             SetError( SbxERR_SYNTAX ); break;
     372             :         }
     373             :     }
     374           0 :     return pVar;
     375             : }
     376             : 
     377          18 : SbxVariable* SbxObject::FindQualified( const OUString& rName, SbxClassType t )
     378             : {
     379          18 :     SbxVariable* pVar = NULL;
     380          18 :     const sal_Unicode* p = rName.getStr();
     381          18 :     p = SkipWhitespace( p );
     382          18 :     if( !*p )
     383             :     {
     384           0 :         return NULL;;
     385             :     }
     386          18 :     pVar = QualifiedName( this, this, &p, t );
     387          18 :     p = SkipWhitespace( p );
     388          18 :     if( *p )
     389             :     {
     390           0 :         SetError( SbxERR_SYNTAX );
     391             :     }
     392          18 :     return pVar;
     393             : }
     394             : 
     395             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11