LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/basic/source/comp - exprnode.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 151 259 58.3 %
Date: 2013-07-09 Functions: 17 21 81.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             : 
      21             : #include <math.h>
      22             : 
      23             : #include <rtl/math.hxx>
      24             : #include "sbcomp.hxx"
      25             : #include "expr.hxx"
      26             : 
      27             : 
      28           0 : SbiExprNode::SbiExprNode( void )
      29             : {
      30           0 :     pLeft = NULL;
      31           0 :     pRight = NULL;
      32           0 :     eNodeType = SbxDUMMY;
      33           0 : }
      34             : 
      35        2812 : SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, SbiToken t, SbiExprNode* r )
      36             : {
      37        2812 :     BaseInit( p );
      38             : 
      39        2812 :     pLeft     = l;
      40        2812 :     pRight    = r;
      41        2812 :     eTok      = t;
      42        2812 :     nVal      = 0;
      43        2812 :     eType     = SbxVARIANT;     // Nodes are always Variant
      44        2812 :     eNodeType = SbxNODE;
      45        2812 : }
      46             : 
      47        1760 : SbiExprNode::SbiExprNode( SbiParser* p, double n, SbxDataType t )
      48             : {
      49        1760 :     BaseInit( p );
      50             : 
      51        1760 :     eType     = t;
      52        1760 :     eNodeType = SbxNUMVAL;
      53        1760 :     nVal      = n;
      54        1760 : }
      55             : 
      56        3348 : SbiExprNode::SbiExprNode( SbiParser* p, const OUString& rVal )
      57             : {
      58        3348 :     BaseInit( p );
      59             : 
      60        3348 :     eType     = SbxSTRING;
      61        3348 :     eNodeType = SbxSTRVAL;
      62        3348 :     aStrVal   = rVal;
      63        3348 : }
      64             : 
      65       12190 : SbiExprNode::SbiExprNode( SbiParser* p, const SbiSymDef& r, SbxDataType t, SbiExprList* l )
      66             : {
      67       12190 :     BaseInit( p );
      68             : 
      69       12190 :     eType     = ( t == SbxVARIANT ) ? r.GetType() : t;
      70       12190 :     eNodeType = SbxVARVAL;
      71       12190 :     aVar.pDef = (SbiSymDef*) &r;
      72       12190 :     aVar.pPar = l;
      73       12190 :     aVar.pvMorePar = NULL;
      74       12190 :     aVar.pNext= NULL;
      75       12190 : }
      76             : 
      77             : // #120061 TypeOf
      78           0 : SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, sal_uInt16 nId )
      79             : {
      80           0 :     BaseInit( p );
      81             : 
      82           0 :     pLeft      = l;
      83           0 :     eType      = SbxBOOL;
      84           0 :     eNodeType  = SbxTYPEOF;
      85           0 :     nTypeStrId = nId;
      86           0 : }
      87             : 
      88             : // new <type>
      89           0 : SbiExprNode::SbiExprNode( SbiParser* p, sal_uInt16 nId )
      90             : {
      91           0 :     BaseInit( p );
      92             : 
      93           0 :     eType     = SbxOBJECT;
      94           0 :     eNodeType = SbxNEW;
      95           0 :     nTypeStrId = nId;
      96           0 : }
      97             : 
      98             : // From 1995-12-17, auxiliary function for Ctor for the uniform initialisation
      99       20110 : void SbiExprNode::BaseInit( SbiParser* p )
     100             : {
     101       20110 :     pGen = &p->aGen;
     102       20110 :     eTok = NIL;
     103       20110 :     pLeft       = NULL;
     104       20110 :     pRight      = NULL;
     105       20110 :     pWithParent = NULL;
     106       20110 :     bError      = false;
     107       20110 : }
     108             : 
     109       60330 : SbiExprNode::~SbiExprNode()
     110             : {
     111       20110 :     delete pLeft;
     112       20110 :     delete pRight;
     113       20110 :     if( IsVariable() )
     114             :     {
     115       12190 :         delete aVar.pPar;
     116       12190 :         delete aVar.pNext;
     117       12190 :         SbiExprListVector* pvMorePar = aVar.pvMorePar;
     118       12190 :         if( pvMorePar )
     119             :         {
     120           0 :             SbiExprListVector::iterator it;
     121           0 :             for( it = pvMorePar->begin() ; it != pvMorePar->end() ; ++it )
     122           0 :                 delete *it;
     123           0 :             delete pvMorePar;
     124             :         }
     125             :     }
     126       40220 : }
     127             : 
     128        3446 : SbiSymDef* SbiExprNode::GetVar()
     129             : {
     130        3446 :     if( eNodeType == SbxVARVAL )
     131        3446 :         return aVar.pDef;
     132             :     else
     133           0 :         return NULL;
     134             : }
     135             : 
     136        3432 : SbiSymDef* SbiExprNode::GetRealVar()
     137             : {
     138        3432 :     SbiExprNode* p = GetRealNode();
     139        3432 :     if( p )
     140        3432 :         return p->GetVar();
     141             :     else
     142           0 :         return NULL;
     143             : }
     144             : 
     145             : // From 1995-12-18
     146        3446 : SbiExprNode* SbiExprNode::GetRealNode()
     147             : {
     148        3446 :     if( eNodeType == SbxVARVAL )
     149             :     {
     150        3446 :         SbiExprNode* p = this;
     151        8024 :         while( p->aVar.pNext )
     152        1132 :             p = p->aVar.pNext;
     153        3446 :         return p;
     154             :     }
     155             :     else
     156           0 :         return NULL;
     157             : }
     158             : 
     159             : // This method transform the type, if it fits into the Integer range
     160             : 
     161          27 : bool SbiExprNode::IsIntConst()
     162             : {
     163          27 :     if( eNodeType == SbxNUMVAL )
     164             :     {
     165          26 :         if( eType >= SbxINTEGER && eType <= SbxDOUBLE )
     166             :         {
     167             :             double n;
     168          26 :             if( nVal >= SbxMININT && nVal <= SbxMAXINT && modf( nVal, &n ) == 0 )
     169             :             {
     170          26 :                 nVal = (double) (short) nVal;
     171          26 :                 eType = SbxINTEGER;
     172          26 :                 return true;
     173             :             }
     174             :         }
     175             :     }
     176           1 :     return false;
     177             : }
     178             : 
     179         313 : bool SbiExprNode::IsNumber()
     180             : {
     181         313 :     return eNodeType == SbxNUMVAL;
     182             : }
     183             : 
     184       22625 : bool SbiExprNode::IsVariable()
     185             : {
     186       22625 :     return eNodeType == SbxVARVAL;
     187             : }
     188             : 
     189        2422 : bool SbiExprNode::IsLvalue()
     190             : {
     191        2422 :     return IsVariable();
     192             : }
     193             : 
     194             : // Identify of the depth of a tree
     195             : 
     196           0 : short SbiExprNode::GetDepth()
     197             : {
     198           0 :     if( IsOperand() ) return 0;
     199             :     else
     200             :     {
     201           0 :         short d1 = pLeft->GetDepth();
     202           0 :         short d2 = pRight->GetDepth();
     203           0 :         return( (d1 < d2 ) ? d2 : d1 ) + 1;
     204             :     }
     205             : }
     206             : 
     207             : 
     208             : // Adjustment of a tree:
     209             : // 1. Constant Folding
     210             : // 2. Type-Adjustment
     211             : // 3. Conversion of the operans into Strings
     212             : // 4. Lifting of the composite- and error-bits
     213             : 
     214        8151 : void SbiExprNode::Optimize()
     215             : {
     216        8151 :     FoldConstants();
     217        8151 :     CollectBits();
     218        8151 : }
     219             : 
     220             : // Lifting of the error-bits
     221             : 
     222       13551 : void SbiExprNode::CollectBits()
     223             : {
     224       13551 :     if( pLeft )
     225             :     {
     226        2744 :         pLeft->CollectBits();
     227        2744 :         bError = bError || pLeft->bError;
     228             :     }
     229       13551 :     if( pRight )
     230             :     {
     231        2624 :         pRight->CollectBits();
     232        2624 :         bError = bError || pRight->bError;
     233             :     }
     234       13551 : }
     235             : 
     236             : // If a twig can be converted, True will be returned. In this case
     237             : // the result is in the left twig.
     238             : 
     239       13587 : void SbiExprNode::FoldConstants()
     240             : {
     241       27174 :     if( IsOperand() || eTok == LIKE ) return;
     242        2812 :     if( pLeft )
     243        2812 :         pLeft->FoldConstants();
     244        2812 :     if( pRight )
     245             :     {
     246        2624 :         pRight->FoldConstants();
     247        5643 :         if( pLeft->IsConstant() && pRight->IsConstant()
     248        2656 :             && pLeft->eNodeType == pRight->eNodeType )
     249             :         {
     250          32 :             CollectBits();
     251          32 :             if( eTok == CAT )
     252             :                 // CAT affiliate also two numbers!
     253           0 :                 eType = SbxSTRING;
     254          32 :             if( pLeft->eType == SbxSTRING )
     255             :                 // No Type Mismatch!
     256          30 :                 eType = SbxSTRING;
     257          32 :             if( eType == SbxSTRING )
     258             :             {
     259          30 :                 OUString rl( pLeft->GetString() );
     260          60 :                 OUString rr( pRight->GetString() );
     261          30 :                 delete pLeft; pLeft = NULL;
     262          30 :                 delete pRight; pRight = NULL;
     263          30 :                 if( eTok == PLUS || eTok == CAT )
     264             :                 {
     265          30 :                     eTok = CAT;
     266             :                     // Linking:
     267          30 :                     aStrVal = rl;
     268          30 :                     aStrVal += rr;
     269          30 :                     eType = SbxSTRING;
     270          30 :                     eNodeType = SbxSTRVAL;
     271             :                 }
     272             :                 else
     273             :                 {
     274           0 :                     eType = SbxDOUBLE;
     275           0 :                     eNodeType = SbxNUMVAL;
     276           0 :                     int eRes = rr.compareTo( rl );
     277           0 :                     switch( eTok )
     278             :                     {
     279             :                     case EQ:
     280           0 :                         nVal = ( eRes == 0 ) ? SbxTRUE : SbxFALSE;
     281           0 :                         break;
     282             :                     case NE:
     283           0 :                         nVal = ( eRes != 0 ) ? SbxTRUE : SbxFALSE;
     284           0 :                         break;
     285             :                     case LT:
     286           0 :                         nVal = ( eRes < 0 ) ? SbxTRUE : SbxFALSE;
     287           0 :                         break;
     288             :                     case GT:
     289           0 :                         nVal = ( eRes > 0 ) ? SbxTRUE : SbxFALSE;
     290           0 :                         break;
     291             :                     case LE:
     292           0 :                         nVal = ( eRes <= 0 ) ? SbxTRUE : SbxFALSE;
     293           0 :                         break;
     294             :                     case GE:
     295           0 :                         nVal = ( eRes >= 0 ) ? SbxTRUE : SbxFALSE;
     296           0 :                         break;
     297             :                     default:
     298           0 :                         pGen->GetParser()->Error( SbERR_CONVERSION );
     299           0 :                         bError = true;
     300           0 :                         break;
     301             :                     }
     302          30 :                 }
     303             :             }
     304             :             else
     305             :             {
     306           2 :                 double nl = pLeft->nVal;
     307           2 :                 double nr = pRight->nVal;
     308           2 :                 long ll = 0, lr = 0;
     309           2 :                 long llMod = 0, lrMod = 0;
     310           2 :                 if( ( eTok >= AND && eTok <= IMP )
     311           2 :                    || eTok == IDIV || eTok == MOD )
     312             :                 {
     313             :                     // Integer operations
     314           0 :                     sal_Bool err = sal_False;
     315           0 :                     if( nl > SbxMAXLNG ) err = sal_True, nl = SbxMAXLNG;
     316           0 :                     else if( nl < SbxMINLNG ) err = sal_True, nl = SbxMINLNG;
     317           0 :                     if( nr > SbxMAXLNG ) err = sal_True, nr = SbxMAXLNG;
     318           0 :                     else if( nr < SbxMINLNG ) err = sal_True, nr = SbxMINLNG;
     319           0 :                     ll = (long) nl; lr = (long) nr;
     320           0 :                     llMod = (long) (nl < 0 ? nl - 0.5 : nl + 0.5);
     321           0 :                     lrMod = (long) (nr < 0 ? nr - 0.5 : nr + 0.5);
     322           0 :                     if( err )
     323             :                     {
     324           0 :                         pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
     325           0 :                         bError = true;
     326             :                     }
     327             :                 }
     328           2 :                 sal_Bool bBothInt = sal_Bool( pLeft->eType < SbxSINGLE
     329           2 :                                    && pRight->eType < SbxSINGLE );
     330           2 :                 delete pLeft; pLeft = NULL;
     331           2 :                 delete pRight; pRight = NULL;
     332           2 :                 nVal = 0;
     333           2 :                 eType = SbxDOUBLE;
     334           2 :                 eNodeType = SbxNUMVAL;
     335           2 :                 sal_Bool bCheckType = sal_False;
     336           2 :                 switch( eTok )
     337             :                 {
     338             :                     case EXPON:
     339           0 :                         nVal = pow( nl, nr ); break;
     340             :                     case MUL:
     341           0 :                         bCheckType = sal_True;
     342           0 :                         nVal = nl * nr; break;
     343             :                     case DIV:
     344           0 :                         if( !nr )
     345             :                         {
     346           0 :                             pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
     347           0 :                             bError = true;
     348           0 :                         } else nVal = nl / nr;
     349           0 :                         break;
     350             :                     case PLUS:
     351           0 :                         bCheckType = sal_True;
     352           0 :                         nVal = nl + nr; break;
     353             :                     case MINUS:
     354           1 :                         bCheckType = sal_True;
     355           1 :                         nVal = nl - nr; break;
     356             :                     case EQ:
     357           1 :                         nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
     358           1 :                         eType = SbxINTEGER; break;
     359             :                     case NE:
     360           0 :                         nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
     361           0 :                         eType = SbxINTEGER; break;
     362             :                     case LT:
     363           0 :                         nVal = ( nl <  nr ) ? SbxTRUE : SbxFALSE;
     364           0 :                         eType = SbxINTEGER; break;
     365             :                     case GT:
     366           0 :                         nVal = ( nl >  nr ) ? SbxTRUE : SbxFALSE;
     367           0 :                         eType = SbxINTEGER; break;
     368             :                     case LE:
     369           0 :                         nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
     370           0 :                         eType = SbxINTEGER; break;
     371             :                     case GE:
     372           0 :                         nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
     373           0 :                         eType = SbxINTEGER; break;
     374             :                     case IDIV:
     375           0 :                         if( !lr )
     376             :                         {
     377           0 :                             pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
     378           0 :                             bError = true;
     379           0 :                         } else nVal = ll / lr;
     380           0 :                         eType = SbxLONG; break;
     381             :                     case MOD:
     382           0 :                         if( !lr )
     383             :                         {
     384           0 :                             pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
     385           0 :                             bError = true;
     386           0 :                         } else nVal = llMod % lrMod;
     387           0 :                         eType = SbxLONG; break;
     388             :                     case AND:
     389           0 :                         nVal = (double) ( ll & lr ); eType = SbxLONG; break;
     390             :                     case OR:
     391           0 :                         nVal = (double) ( ll | lr ); eType = SbxLONG; break;
     392             :                     case XOR:
     393           0 :                         nVal = (double) ( ll ^ lr ); eType = SbxLONG; break;
     394             :                     case EQV:
     395           0 :                         nVal = (double) ( ~ll ^ lr ); eType = SbxLONG; break;
     396             :                     case IMP:
     397           0 :                         nVal = (double) ( ~ll | lr ); eType = SbxLONG; break;
     398           0 :                     default: break;
     399             :                 }
     400             : 
     401           2 :                 if( !::rtl::math::isFinite( nVal ) )
     402           0 :                     pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
     403             : 
     404             :                 // Recover the data type to kill rounding error
     405           2 :                 if( bCheckType && bBothInt
     406           1 :                  && nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
     407             :                 {
     408             :                     // Decimal place away
     409           1 :                     long n = (long) nVal;
     410           1 :                     nVal = n;
     411           1 :                     eType = ( n >= SbxMININT && n <= SbxMAXINT )
     412           2 :                           ? SbxINTEGER : SbxLONG;
     413             :                 }
     414             :             }
     415             :         }
     416             :     }
     417         188 :     else if( pLeft && pLeft->IsNumber() )
     418             :     {
     419          68 :         nVal = pLeft->nVal;
     420          68 :         delete pLeft;
     421          68 :         pLeft = NULL;
     422          68 :         eType = SbxDOUBLE;
     423          68 :         eNodeType = SbxNUMVAL;
     424          68 :         switch( eTok )
     425             :         {
     426             :             case NEG:
     427          68 :                 nVal = -nVal; break;
     428             :             case NOT: {
     429             :                 // Integer operation!
     430           0 :                 sal_Bool err = sal_False;
     431           0 :                 if( nVal > SbxMAXLNG ) err = sal_True, nVal = SbxMAXLNG;
     432           0 :                 else if( nVal < SbxMINLNG ) err = sal_True, nVal = SbxMINLNG;
     433           0 :                 if( err )
     434             :                 {
     435           0 :                     pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
     436           0 :                     bError = true;
     437             :                 }
     438           0 :                 nVal = (double) ~((long) nVal);
     439           0 :                 eType = SbxLONG;
     440           0 :                 } break;
     441           0 :             default: break;
     442             :         }
     443             :     }
     444        2812 :     if( eNodeType == SbxNUMVAL )
     445             :     {
     446             :         // Potentially convolve in INTEGER (because of better opcode)?
     447          70 :         if( eType == SbxSINGLE || eType == SbxDOUBLE )
     448             :         {
     449             :             double x;
     450         204 :             if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG
     451         136 :             && !modf( nVal, &x ) )
     452          62 :                 eType = SbxLONG;
     453             :         }
     454          70 :         if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
     455          62 :             eType = SbxINTEGER;
     456             :     }
     457             : }
     458             : 
     459             : 
     460             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10