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

Generated by: LCOV version 1.10