LCOV - code coverage report
Current view: top level - basic/source/comp - exprnode.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 151 264 57.2 %
Date: 2014-04-11 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        2787 : SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, SbiToken t, SbiExprNode* r )
      41             : {
      42        2787 :     BaseInit( p );
      43             : 
      44        2787 :     pLeft     = l;
      45        2787 :     pRight    = r;
      46        2787 :     eTok      = t;
      47        2787 :     nVal      = 0;
      48        2787 :     eType     = SbxVARIANT;     // Nodes are always Variant
      49        2787 :     eNodeType = SbxNODE;
      50        2787 : }
      51             : 
      52        1790 : SbiExprNode::SbiExprNode( SbiParser* p, double n, SbxDataType t )
      53             : {
      54        1790 :     BaseInit( p );
      55             : 
      56        1790 :     eType     = t;
      57        1790 :     eNodeType = SbxNUMVAL;
      58        1790 :     nVal      = n;
      59        1790 : }
      60             : 
      61        3333 : SbiExprNode::SbiExprNode( SbiParser* p, const OUString& rVal )
      62             : {
      63        3333 :     BaseInit( p );
      64             : 
      65        3333 :     eType     = SbxSTRING;
      66        3333 :     eNodeType = SbxSTRVAL;
      67        3333 :     aStrVal   = rVal;
      68        3333 : }
      69             : 
      70       12135 : SbiExprNode::SbiExprNode( SbiParser* p, const SbiSymDef& r, SbxDataType t, SbiExprList* l )
      71             : {
      72       12135 :     BaseInit( p );
      73             : 
      74       12135 :     eType     = ( t == SbxVARIANT ) ? r.GetType() : t;
      75       12135 :     eNodeType = SbxVARVAL;
      76       12135 :     aVar.pDef = (SbiSymDef*) &r;
      77       12135 :     aVar.pPar = l;
      78       12135 :     aVar.pvMorePar = NULL;
      79       12135 :     aVar.pNext= NULL;
      80       12135 : }
      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       20045 : void SbiExprNode::BaseInit( SbiParser* p )
     105             : {
     106       20045 :     pGen = &p->aGen;
     107       20045 :     eTok = NIL;
     108       20045 :     pLeft       = NULL;
     109       20045 :     pRight      = NULL;
     110       20045 :     pWithParent = NULL;
     111       20045 :     bError      = false;
     112       20045 : }
     113             : 
     114       60135 : SbiExprNode::~SbiExprNode()
     115             : {
     116       20045 :     delete pLeft;
     117       20045 :     delete pRight;
     118       20045 :     if( IsVariable() )
     119             :     {
     120       12135 :         delete aVar.pPar;
     121       12135 :         delete aVar.pNext;
     122       12135 :         SbiExprListVector* pvMorePar = aVar.pvMorePar;
     123       12135 :         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       40090 : }
     132             : 
     133        3447 : SbiSymDef* SbiExprNode::GetVar()
     134             : {
     135        3447 :     if( eNodeType == SbxVARVAL )
     136        3447 :         return aVar.pDef;
     137             :     else
     138           0 :         return NULL;
     139             : }
     140             : 
     141        3433 : SbiSymDef* SbiExprNode::GetRealVar()
     142             : {
     143        3433 :     SbiExprNode* p = GetRealNode();
     144        3433 :     if( p )
     145        3433 :         return p->GetVar();
     146             :     else
     147           0 :         return NULL;
     148             : }
     149             : 
     150             : // From 1995-12-18
     151        3447 : SbiExprNode* SbiExprNode::GetRealNode()
     152             : {
     153        3447 :     if( eNodeType == SbxVARVAL )
     154             :     {
     155        3447 :         SbiExprNode* p = this;
     156        8023 :         while( p->aVar.pNext )
     157        1129 :             p = p->aVar.pNext;
     158        3447 :         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          28 : bool SbiExprNode::IsIntConst()
     167             : {
     168          28 :     if( eNodeType == SbxNUMVAL )
     169             :     {
     170          27 :         if( eType >= SbxINTEGER && eType <= SbxDOUBLE )
     171             :         {
     172             :             double n;
     173          27 :             if( nVal >= SbxMININT && nVal <= SbxMAXINT && modf( nVal, &n ) == 0 )
     174             :             {
     175          27 :                 nVal = (double) (short) nVal;
     176          27 :                 eType = SbxINTEGER;
     177          27 :                 return true;
     178             :             }
     179             :         }
     180             :     }
     181           1 :     return false;
     182             : }
     183             : 
     184         308 : bool SbiExprNode::IsNumber()
     185             : {
     186         308 :     return eNodeType == SbxNUMVAL;
     187             : }
     188             : 
     189       22572 : bool SbiExprNode::IsVariable()
     190             : {
     191       22572 :     return eNodeType == SbxVARVAL;
     192             : }
     193             : 
     194        2434 : bool SbiExprNode::IsLvalue()
     195             : {
     196        2434 :     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        8138 : void SbiExprNode::Optimize()
     220             : {
     221        8138 :     FoldConstants();
     222        8138 :     CollectBits();
     223        8138 : }
     224             : 
     225             : // Lifting of the error-bits
     226             : 
     227       13488 : void SbiExprNode::CollectBits()
     228             : {
     229       13488 :     if( pLeft )
     230             :     {
     231        2717 :         pLeft->CollectBits();
     232        2717 :         bError = bError || pLeft->bError;
     233             :     }
     234       13488 :     if( pRight )
     235             :     {
     236        2601 :         pRight->CollectBits();
     237        2601 :         bError = bError || pRight->bError;
     238             :     }
     239       13488 : }
     240             : 
     241             : // If a twig can be converted, True will be returned. In this case
     242             : // the result is in the left twig.
     243             : 
     244       13526 : void SbiExprNode::FoldConstants()
     245             : {
     246       27052 :     if( IsOperand() || eTok == LIKE ) return;
     247        2787 :     if( pLeft )
     248        2787 :         pLeft->FoldConstants();
     249        2787 :     if( pRight )
     250             :     {
     251        2601 :         pRight->FoldConstants();
     252        5596 :         if( pLeft->IsConstant() && pRight->IsConstant()
     253        2633 :             && pLeft->eNodeType == pRight->eNodeType )
     254             :         {
     255          32 :             CollectBits();
     256          32 :             if( eTok == CAT )
     257             :                 // CAT affiliate also two numbers!
     258           0 :                 eType = SbxSTRING;
     259          32 :             if( pLeft->eType == SbxSTRING )
     260             :                 // No Type Mismatch!
     261          30 :                 eType = SbxSTRING;
     262          32 :             if( eType == SbxSTRING )
     263             :             {
     264          30 :                 OUString rl( pLeft->GetString() );
     265          60 :                 OUString rr( pRight->GetString() );
     266          30 :                 delete pLeft; pLeft = NULL;
     267          30 :                 delete pRight; pRight = NULL;
     268          30 :                 if( eTok == PLUS || eTok == CAT )
     269             :                 {
     270          30 :                     eTok = CAT;
     271             :                     // Linking:
     272          30 :                     aStrVal = rl;
     273          30 :                     aStrVal += rr;
     274          30 :                     eType = SbxSTRING;
     275          30 :                     eNodeType = SbxSTRVAL;
     276             :                 }
     277             :                 else
     278             :                 {
     279           0 :                     eType = SbxDOUBLE;
     280           0 :                     eNodeType = SbxNUMVAL;
     281           0 :                     int eRes = rr.compareTo( rl );
     282           0 :                     switch( eTok )
     283             :                     {
     284             :                     case EQ:
     285           0 :                         nVal = ( eRes == 0 ) ? SbxTRUE : SbxFALSE;
     286           0 :                         break;
     287             :                     case NE:
     288           0 :                         nVal = ( eRes != 0 ) ? SbxTRUE : SbxFALSE;
     289           0 :                         break;
     290             :                     case LT:
     291           0 :                         nVal = ( eRes < 0 ) ? SbxTRUE : SbxFALSE;
     292           0 :                         break;
     293             :                     case GT:
     294           0 :                         nVal = ( eRes > 0 ) ? SbxTRUE : SbxFALSE;
     295           0 :                         break;
     296             :                     case LE:
     297           0 :                         nVal = ( eRes <= 0 ) ? SbxTRUE : SbxFALSE;
     298           0 :                         break;
     299             :                     case GE:
     300           0 :                         nVal = ( eRes >= 0 ) ? SbxTRUE : SbxFALSE;
     301           0 :                         break;
     302             :                     default:
     303           0 :                         pGen->GetParser()->Error( SbERR_CONVERSION );
     304           0 :                         bError = true;
     305           0 :                         break;
     306             :                     }
     307          30 :                 }
     308             :             }
     309             :             else
     310             :             {
     311           2 :                 double nl = pLeft->nVal;
     312           2 :                 double nr = pRight->nVal;
     313           2 :                 long ll = 0, lr = 0;
     314           2 :                 long llMod = 0, lrMod = 0;
     315           2 :                 if( ( eTok >= AND && eTok <= IMP )
     316           2 :                    || eTok == IDIV || eTok == MOD )
     317             :                 {
     318             :                     // Integer operations
     319           0 :                     bool err = false;
     320           0 :                     if( nl > SbxMAXLNG ) err = true, nl = SbxMAXLNG;
     321           0 :                     else if( nl < SbxMINLNG ) err = true, nl = SbxMINLNG;
     322           0 :                     if( nr > SbxMAXLNG ) err = true, nr = SbxMAXLNG;
     323           0 :                     else if( nr < SbxMINLNG ) err = true, nr = SbxMINLNG;
     324           0 :                     ll = (long) nl; lr = (long) nr;
     325           0 :                     llMod = (long) (nl < 0 ? nl - 0.5 : nl + 0.5);
     326           0 :                     lrMod = (long) (nr < 0 ? nr - 0.5 : nr + 0.5);
     327           0 :                     if( err )
     328             :                     {
     329           0 :                         pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
     330           0 :                         bError = true;
     331             :                     }
     332             :                 }
     333           2 :                 bool bBothInt = ( pLeft->eType < SbxSINGLE
     334           2 :                                    && pRight->eType < SbxSINGLE );
     335           2 :                 delete pLeft; pLeft = NULL;
     336           2 :                 delete pRight; pRight = NULL;
     337           2 :                 nVal = 0;
     338           2 :                 eType = SbxDOUBLE;
     339           2 :                 eNodeType = SbxNUMVAL;
     340           2 :                 bool bCheckType = false;
     341           2 :                 switch( eTok )
     342             :                 {
     343             :                     case EXPON:
     344           0 :                         nVal = pow( nl, nr ); break;
     345             :                     case MUL:
     346           0 :                         bCheckType = true;
     347           0 :                         nVal = nl * nr; break;
     348             :                     case DIV:
     349           0 :                         if( !nr )
     350             :                         {
     351           0 :                             pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
     352           0 :                             bError = true;
     353           0 :                         } else nVal = nl / nr;
     354           0 :                         break;
     355             :                     case PLUS:
     356           0 :                         bCheckType = true;
     357           0 :                         nVal = nl + nr; break;
     358             :                     case MINUS:
     359           1 :                         bCheckType = true;
     360           1 :                         nVal = nl - nr; break;
     361             :                     case EQ:
     362           1 :                         nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
     363           1 :                         eType = SbxINTEGER; break;
     364             :                     case NE:
     365           0 :                         nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
     366           0 :                         eType = SbxINTEGER; break;
     367             :                     case LT:
     368           0 :                         nVal = ( nl <  nr ) ? SbxTRUE : SbxFALSE;
     369           0 :                         eType = SbxINTEGER; break;
     370             :                     case GT:
     371           0 :                         nVal = ( nl >  nr ) ? SbxTRUE : SbxFALSE;
     372           0 :                         eType = SbxINTEGER; break;
     373             :                     case LE:
     374           0 :                         nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
     375           0 :                         eType = SbxINTEGER; break;
     376             :                     case GE:
     377           0 :                         nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
     378           0 :                         eType = SbxINTEGER; break;
     379             :                     case IDIV:
     380           0 :                         if( !lr )
     381             :                         {
     382           0 :                             pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
     383           0 :                             bError = true;
     384           0 :                         } else nVal = ll / lr;
     385           0 :                         eType = SbxLONG; break;
     386             :                     case MOD:
     387           0 :                         if( !lr )
     388             :                         {
     389           0 :                             pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
     390           0 :                             bError = true;
     391           0 :                         } else nVal = llMod % lrMod;
     392           0 :                         eType = SbxLONG; break;
     393             :                     case AND:
     394           0 :                         nVal = (double) ( ll & lr ); eType = SbxLONG; break;
     395             :                     case OR:
     396           0 :                         nVal = (double) ( ll | lr ); eType = SbxLONG; break;
     397             :                     case XOR:
     398           0 :                         nVal = (double) ( ll ^ lr ); eType = SbxLONG; break;
     399             :                     case EQV:
     400           0 :                         nVal = (double) ( ~ll ^ lr ); eType = SbxLONG; break;
     401             :                     case IMP:
     402           0 :                         nVal = (double) ( ~ll | lr ); eType = SbxLONG; break;
     403           0 :                     default: break;
     404             :                 }
     405             : 
     406           2 :                 if( !::rtl::math::isFinite( nVal ) )
     407           0 :                     pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
     408             : 
     409             :                 // Recover the data type to kill rounding error
     410           2 :                 if( bCheckType && bBothInt
     411           1 :                  && nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
     412             :                 {
     413             :                     // Decimal place away
     414           1 :                     long n = (long) nVal;
     415           1 :                     nVal = n;
     416           1 :                     eType = ( n >= SbxMININT && n <= SbxMAXINT )
     417           2 :                           ? SbxINTEGER : SbxLONG;
     418             :                 }
     419             :             }
     420             :         }
     421             :     }
     422         186 :     else if( pLeft && pLeft->IsNumber() )
     423             :     {
     424          70 :         nVal = pLeft->nVal;
     425          70 :         delete pLeft;
     426          70 :         pLeft = NULL;
     427          70 :         eType = SbxDOUBLE;
     428          70 :         eNodeType = SbxNUMVAL;
     429          70 :         switch( eTok )
     430             :         {
     431             :             case NEG:
     432          70 :                 nVal = -nVal; break;
     433             :             case NOT: {
     434             :                 // Integer operation!
     435           0 :                 bool err = false;
     436           0 :                 if( nVal > SbxMAXLNG ) err = true, nVal = SbxMAXLNG;
     437           0 :                 else if( nVal < SbxMINLNG ) err = true, nVal = SbxMINLNG;
     438           0 :                 if( err )
     439             :                 {
     440           0 :                     pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
     441           0 :                     bError = true;
     442             :                 }
     443           0 :                 nVal = (double) ~((long) nVal);
     444           0 :                 eType = SbxLONG;
     445           0 :                 } break;
     446           0 :             default: break;
     447             :         }
     448             :     }
     449        2787 :     if( eNodeType == SbxNUMVAL )
     450             :     {
     451             :         // Potentially convolve in INTEGER (because of better opcode)?
     452          72 :         if( eType == SbxSINGLE || eType == SbxDOUBLE )
     453             :         {
     454             :             double x;
     455         210 :             if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG
     456         140 :             && !modf( nVal, &x ) )
     457          64 :                 eType = SbxLONG;
     458             :         }
     459          72 :         if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
     460          63 :             eType = SbxINTEGER;
     461             :     }
     462             : }
     463             : 
     464             : 
     465             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10