1e1f63238SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3e1f63238SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4e1f63238SAndrew Rist * or more contributor license agreements. See the NOTICE file 5e1f63238SAndrew Rist * distributed with this work for additional information 6e1f63238SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7e1f63238SAndrew Rist * to you under the Apache License, Version 2.0 (the 8e1f63238SAndrew Rist * "License"); you may not use this file except in compliance 9e1f63238SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11e1f63238SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13e1f63238SAndrew Rist * Unless required by applicable law or agreed to in writing, 14e1f63238SAndrew Rist * software distributed under the License is distributed on an 15e1f63238SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16e1f63238SAndrew Rist * KIND, either express or implied. See the License for the 17e1f63238SAndrew Rist * specific language governing permissions and limitations 18e1f63238SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20e1f63238SAndrew Rist *************************************************************/ 21e1f63238SAndrew Rist 22e1f63238SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_basic.hxx" 26cdf0e10cSrcweir #include <tools/errcode.hxx> 27cdf0e10cSrcweir #ifndef _APP_HXX //autogen 28cdf0e10cSrcweir #include <vcl/svapp.hxx> 29cdf0e10cSrcweir #endif 30cdf0e10cSrcweir #include <basic/sbx.hxx> 31cdf0e10cSrcweir 32cdf0e10cSrcweir 33cdf0e10cSrcweir class SbxSimpleCharClass 34cdf0e10cSrcweir { 35cdf0e10cSrcweir public: 36cdf0e10cSrcweir sal_Bool isAlpha( sal_Unicode c ) const 37cdf0e10cSrcweir { 38cdf0e10cSrcweir sal_Bool bRet = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); 39cdf0e10cSrcweir return bRet; 40cdf0e10cSrcweir } 41cdf0e10cSrcweir 42cdf0e10cSrcweir sal_Bool isDigit( sal_Unicode c ) const 43cdf0e10cSrcweir { 44cdf0e10cSrcweir sal_Bool bRet = (c >= '0' && c <= '9'); 45cdf0e10cSrcweir return bRet; 46cdf0e10cSrcweir } 47cdf0e10cSrcweir 48cdf0e10cSrcweir sal_Bool isAlphaNumeric( sal_Unicode c ) const 49cdf0e10cSrcweir { 50cdf0e10cSrcweir sal_Bool bRet = isDigit( c ) || isAlpha( c ); 51cdf0e10cSrcweir return bRet; 52cdf0e10cSrcweir } 53cdf0e10cSrcweir }; 54cdf0e10cSrcweir 55cdf0e10cSrcweir 56cdf0e10cSrcweir static SbxVariable* Element 57cdf0e10cSrcweir ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, 58cdf0e10cSrcweir SbxClassType, const SbxSimpleCharClass& rCharClass ); 59cdf0e10cSrcweir 60cdf0e10cSrcweir static const xub_Unicode* SkipWhitespace( const xub_Unicode* p ) 61cdf0e10cSrcweir { 62cdf0e10cSrcweir while( *p && ( *p == ' ' || *p == '\t' ) ) 63cdf0e10cSrcweir p++; 64cdf0e10cSrcweir return p; 65cdf0e10cSrcweir } 66cdf0e10cSrcweir 67cdf0e10cSrcweir // Scannen eines Symbol. Das Symbol wird in rSym eingetragen, der Returnwert 68cdf0e10cSrcweir // ist die neue Scanposition. Bei Fehlern ist das Symbol leer. 69cdf0e10cSrcweir 70cdf0e10cSrcweir static const xub_Unicode* Symbol( const xub_Unicode* p, XubString& rSym, const SbxSimpleCharClass& rCharClass ) 71cdf0e10cSrcweir { 72cdf0e10cSrcweir sal_uInt16 nLen = 0; 73cdf0e10cSrcweir // Haben wir ein Sondersymbol? 74cdf0e10cSrcweir if( *p == '[' ) 75cdf0e10cSrcweir { 76cdf0e10cSrcweir rSym = ++p; 77cdf0e10cSrcweir while( *p && *p != ']' ) 78cdf0e10cSrcweir p++, nLen++; 79cdf0e10cSrcweir p++; 80cdf0e10cSrcweir } 81cdf0e10cSrcweir else 82cdf0e10cSrcweir { 83cdf0e10cSrcweir // Ein Symbol muss mit einem Buchstaben oder einem Underline beginnen 84cdf0e10cSrcweir if( !rCharClass.isAlpha( *p ) && *p != '_' ) 85cdf0e10cSrcweir SbxBase::SetError( SbxERR_SYNTAX ); 86cdf0e10cSrcweir else 87cdf0e10cSrcweir { 88cdf0e10cSrcweir rSym = p; 89cdf0e10cSrcweir // Dann darf es Buchstaben, Zahlen oder Underlines enthalten 90cdf0e10cSrcweir while( *p && (rCharClass.isAlphaNumeric( *p ) || *p == '_') ) 91cdf0e10cSrcweir p++, nLen++; 92cdf0e10cSrcweir // BASIC-Standard-Suffixe werden ignoriert 93cdf0e10cSrcweir if( *p && (*p == '%' || *p == '&' || *p == '!' || *p == '#' || *p == '$' ) ) 94cdf0e10cSrcweir p++; 95cdf0e10cSrcweir } 96cdf0e10cSrcweir } 97cdf0e10cSrcweir rSym.Erase( nLen ); 98cdf0e10cSrcweir return p; 99cdf0e10cSrcweir } 100cdf0e10cSrcweir 101cdf0e10cSrcweir // Qualifizierter Name. Element.Element.... 102cdf0e10cSrcweir 103cdf0e10cSrcweir static SbxVariable* QualifiedName 104cdf0e10cSrcweir ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, SbxClassType t ) 105cdf0e10cSrcweir { 106cdf0e10cSrcweir static SbxSimpleCharClass aCharClass; 107cdf0e10cSrcweir 108cdf0e10cSrcweir SbxVariableRef refVar; 109cdf0e10cSrcweir const xub_Unicode* p = SkipWhitespace( *ppBuf ); 110cdf0e10cSrcweir if( aCharClass.isAlpha( *p ) || *p == '_' || *p == '[' ) 111cdf0e10cSrcweir { 112cdf0e10cSrcweir // Element einlesen 113cdf0e10cSrcweir refVar = Element( pObj, pGbl, &p, t, aCharClass ); 114cdf0e10cSrcweir while( refVar.Is() && (*p == '.' || *p == '!') ) 115cdf0e10cSrcweir { 116cdf0e10cSrcweir // Es folgt noch ein Objektelement. Das aktuelle Element 117cdf0e10cSrcweir // muss also ein SBX-Objekt sein oder liefern! 118cdf0e10cSrcweir pObj = PTR_CAST(SbxObject,(SbxVariable*) refVar); 119cdf0e10cSrcweir if( !pObj ) 120cdf0e10cSrcweir // Dann muss es ein Objekt liefern 121cdf0e10cSrcweir pObj = PTR_CAST(SbxObject,refVar->GetObject()); 122cdf0e10cSrcweir refVar.Clear(); 123cdf0e10cSrcweir if( !pObj ) 124cdf0e10cSrcweir break; 125cdf0e10cSrcweir p++; 126cdf0e10cSrcweir // Und das naechste Element bitte 127cdf0e10cSrcweir refVar = Element( pObj, pGbl, &p, t, aCharClass ); 128cdf0e10cSrcweir } 129cdf0e10cSrcweir } 130cdf0e10cSrcweir else 131cdf0e10cSrcweir SbxBase::SetError( SbxERR_SYNTAX ); 132cdf0e10cSrcweir *ppBuf = p; 133cdf0e10cSrcweir if( refVar.Is() ) 134cdf0e10cSrcweir refVar->AddRef(); 135cdf0e10cSrcweir return refVar; 136cdf0e10cSrcweir } 137cdf0e10cSrcweir 138cdf0e10cSrcweir // Einlesen eines Operanden. Dies kann eine Zahl, ein String oder 139cdf0e10cSrcweir // eine Funktion (mit optionalen Parametern) sein. 140cdf0e10cSrcweir 141cdf0e10cSrcweir static SbxVariable* Operand 142cdf0e10cSrcweir ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, sal_Bool bVar ) 143cdf0e10cSrcweir { 144cdf0e10cSrcweir static SbxSimpleCharClass aCharClass; 145cdf0e10cSrcweir 146cdf0e10cSrcweir SbxVariableRef refVar( new SbxVariable ); 147cdf0e10cSrcweir const xub_Unicode* p = SkipWhitespace( *ppBuf ); 148cdf0e10cSrcweir if( !bVar && ( aCharClass.isDigit( *p ) 149cdf0e10cSrcweir || ( *p == '.' && aCharClass.isDigit( *( p+1 ) ) ) 150cdf0e10cSrcweir || *p == '-' 151cdf0e10cSrcweir || *p == '&' ) ) 152cdf0e10cSrcweir { 153cdf0e10cSrcweir // Eine Zahl kann direkt eingescant werden! 154cdf0e10cSrcweir sal_uInt16 nLen; 155cdf0e10cSrcweir if( !refVar->Scan( XubString( p ), &nLen ) ) 156cdf0e10cSrcweir refVar.Clear(); 157cdf0e10cSrcweir else 158cdf0e10cSrcweir p += nLen; 159cdf0e10cSrcweir } 160cdf0e10cSrcweir else if( !bVar && *p == '"' ) 161cdf0e10cSrcweir { 162cdf0e10cSrcweir // Ein String 163cdf0e10cSrcweir XubString aString; 164cdf0e10cSrcweir p++; 165cdf0e10cSrcweir for( ;; ) 166cdf0e10cSrcweir { 167cdf0e10cSrcweir // Das ist wohl ein Fehler 168cdf0e10cSrcweir if( !*p ) 169cdf0e10cSrcweir return NULL; 170cdf0e10cSrcweir // Doppelte Quotes sind OK 171cdf0e10cSrcweir if( *p == '"' ) 172cdf0e10cSrcweir if( *++p != '"' ) 173cdf0e10cSrcweir break; 174cdf0e10cSrcweir aString += *p++; 175cdf0e10cSrcweir } 176cdf0e10cSrcweir refVar->PutString( aString ); 177cdf0e10cSrcweir } 178cdf0e10cSrcweir else 179cdf0e10cSrcweir refVar = QualifiedName( pObj, pGbl, &p, SbxCLASS_DONTCARE ); 180cdf0e10cSrcweir *ppBuf = p; 181cdf0e10cSrcweir if( refVar.Is() ) 182cdf0e10cSrcweir refVar->AddRef(); 183cdf0e10cSrcweir return refVar; 184cdf0e10cSrcweir } 185cdf0e10cSrcweir 186cdf0e10cSrcweir // Einlesen einer einfachen Term. Die Operatoren +, -, * und / 187cdf0e10cSrcweir // werden unterstuetzt. 188cdf0e10cSrcweir 189cdf0e10cSrcweir static SbxVariable* MulDiv( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf ) 190cdf0e10cSrcweir { 191cdf0e10cSrcweir const xub_Unicode* p = *ppBuf; 192cdf0e10cSrcweir SbxVariableRef refVar( Operand( pObj, pGbl, &p, sal_False ) ); 193cdf0e10cSrcweir p = SkipWhitespace( p ); 194cdf0e10cSrcweir while( refVar.Is() && ( *p == '*' || *p == '/' ) ) 195cdf0e10cSrcweir { 196cdf0e10cSrcweir xub_Unicode cOp = *p++; 197cdf0e10cSrcweir SbxVariableRef refVar2( Operand( pObj, pGbl, &p, sal_False ) ); 198cdf0e10cSrcweir if( refVar2.Is() ) 199cdf0e10cSrcweir { 200cdf0e10cSrcweir // temporaere Variable! 201cdf0e10cSrcweir SbxVariable* pVar = refVar; 202cdf0e10cSrcweir pVar = new SbxVariable( *pVar ); 203cdf0e10cSrcweir refVar = pVar; 204cdf0e10cSrcweir if( cOp == '*' ) 205cdf0e10cSrcweir *refVar *= *refVar2; 206cdf0e10cSrcweir else 207cdf0e10cSrcweir *refVar /= *refVar2; 208cdf0e10cSrcweir } 209cdf0e10cSrcweir else 210cdf0e10cSrcweir { 211cdf0e10cSrcweir refVar.Clear(); 212cdf0e10cSrcweir break; 213cdf0e10cSrcweir } 214cdf0e10cSrcweir } 215cdf0e10cSrcweir *ppBuf = p; 216cdf0e10cSrcweir if( refVar.Is() ) 217cdf0e10cSrcweir refVar->AddRef(); 218cdf0e10cSrcweir return refVar; 219cdf0e10cSrcweir } 220cdf0e10cSrcweir 221cdf0e10cSrcweir static SbxVariable* PlusMinus( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf ) 222cdf0e10cSrcweir { 223cdf0e10cSrcweir const xub_Unicode* p = *ppBuf; 224cdf0e10cSrcweir SbxVariableRef refVar( MulDiv( pObj, pGbl, &p ) ); 225cdf0e10cSrcweir p = SkipWhitespace( p ); 226cdf0e10cSrcweir while( refVar.Is() && ( *p == '+' || *p == '-' ) ) 227cdf0e10cSrcweir { 228cdf0e10cSrcweir xub_Unicode cOp = *p++; 229cdf0e10cSrcweir SbxVariableRef refVar2( MulDiv( pObj, pGbl, &p ) ); 230cdf0e10cSrcweir if( refVar2.Is() ) 231cdf0e10cSrcweir { 232cdf0e10cSrcweir // temporaere Variable! 233cdf0e10cSrcweir SbxVariable* pVar = refVar; 234cdf0e10cSrcweir pVar = new SbxVariable( *pVar ); 235cdf0e10cSrcweir refVar = pVar; 236cdf0e10cSrcweir if( cOp == '+' ) 237cdf0e10cSrcweir *refVar += *refVar2; 238cdf0e10cSrcweir else 239cdf0e10cSrcweir *refVar -= *refVar2; 240cdf0e10cSrcweir } 241cdf0e10cSrcweir else 242cdf0e10cSrcweir { 243cdf0e10cSrcweir refVar.Clear(); 244cdf0e10cSrcweir break; 245cdf0e10cSrcweir } 246cdf0e10cSrcweir } 247cdf0e10cSrcweir *ppBuf = p; 248cdf0e10cSrcweir if( refVar.Is() ) 249cdf0e10cSrcweir refVar->AddRef(); 250cdf0e10cSrcweir return refVar; 251cdf0e10cSrcweir } 252cdf0e10cSrcweir 253cdf0e10cSrcweir static SbxVariable* Assign( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf ) 254cdf0e10cSrcweir { 255cdf0e10cSrcweir const xub_Unicode* p = *ppBuf; 256cdf0e10cSrcweir SbxVariableRef refVar( Operand( pObj, pGbl, &p, sal_True ) ); 257cdf0e10cSrcweir p = SkipWhitespace( p ); 258cdf0e10cSrcweir if( refVar.Is() ) 259cdf0e10cSrcweir { 260cdf0e10cSrcweir if( *p == '=' ) 261cdf0e10cSrcweir { 262cdf0e10cSrcweir // Nur auf Props zuweisen! 263cdf0e10cSrcweir if( refVar->GetClass() != SbxCLASS_PROPERTY ) 264cdf0e10cSrcweir { 265cdf0e10cSrcweir SbxBase::SetError( SbxERR_BAD_ACTION ); 266cdf0e10cSrcweir refVar.Clear(); 267cdf0e10cSrcweir } 268cdf0e10cSrcweir else 269cdf0e10cSrcweir { 270cdf0e10cSrcweir p++; 271cdf0e10cSrcweir SbxVariableRef refVar2( PlusMinus( pObj, pGbl, &p ) ); 272cdf0e10cSrcweir if( refVar2.Is() ) 273cdf0e10cSrcweir { 274cdf0e10cSrcweir SbxVariable* pVar = refVar; 275cdf0e10cSrcweir SbxVariable* pVar2 = refVar2; 276cdf0e10cSrcweir *pVar = *pVar2; 277cdf0e10cSrcweir pVar->SetParameters( NULL ); 278cdf0e10cSrcweir } 279cdf0e10cSrcweir } 280cdf0e10cSrcweir } 281cdf0e10cSrcweir else 282cdf0e10cSrcweir // Einfacher Aufruf: einmal aktivieren 283cdf0e10cSrcweir refVar->Broadcast( SBX_HINT_DATAWANTED ); 284cdf0e10cSrcweir } 285cdf0e10cSrcweir *ppBuf = p; 286cdf0e10cSrcweir if( refVar.Is() ) 287cdf0e10cSrcweir refVar->AddRef(); 288cdf0e10cSrcweir return refVar; 289cdf0e10cSrcweir } 290cdf0e10cSrcweir 291cdf0e10cSrcweir // Einlesen eines Elements. Dies ist ein Symbol, optional gefolgt 292cdf0e10cSrcweir // von einer Parameterliste. Das Symbol wird im angegebenen Objekt 293cdf0e10cSrcweir // gesucht und die Parameterliste wird ggf. angefuegt. 294cdf0e10cSrcweir 295cdf0e10cSrcweir static SbxVariable* Element 296cdf0e10cSrcweir ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, 297cdf0e10cSrcweir SbxClassType t, const SbxSimpleCharClass& rCharClass ) 298cdf0e10cSrcweir { 299cdf0e10cSrcweir XubString aSym; 300cdf0e10cSrcweir const xub_Unicode* p = Symbol( *ppBuf, aSym, rCharClass ); 301cdf0e10cSrcweir SbxVariableRef refVar; 302cdf0e10cSrcweir if( aSym.Len() ) 303cdf0e10cSrcweir { 304cdf0e10cSrcweir sal_uInt16 nOld = pObj->GetFlags(); 305cdf0e10cSrcweir if( pObj == pGbl ) 306cdf0e10cSrcweir pObj->SetFlag( SBX_GBLSEARCH ); 307cdf0e10cSrcweir refVar = pObj->Find( aSym, t ); 308cdf0e10cSrcweir pObj->SetFlags( nOld ); 309cdf0e10cSrcweir if( refVar.Is() ) 310cdf0e10cSrcweir { 311cdf0e10cSrcweir refVar->SetParameters( NULL ); 312cdf0e10cSrcweir // folgen noch Parameter? 313cdf0e10cSrcweir p = SkipWhitespace( p ); 314cdf0e10cSrcweir if( *p == '(' ) 315cdf0e10cSrcweir { 316cdf0e10cSrcweir p++; 317cdf0e10cSrcweir SbxArrayRef refPar = new SbxArray; 318cdf0e10cSrcweir sal_uInt16 nArg = 0; 319cdf0e10cSrcweir // Wird sind mal relaxed und akzeptieren auch 320cdf0e10cSrcweir // das Zeilen- oder Komandoende als Begrenzer 321cdf0e10cSrcweir // Parameter immer global suchen! 322cdf0e10cSrcweir while( *p && *p != ')' && *p != ']' ) 323cdf0e10cSrcweir { 324cdf0e10cSrcweir SbxVariableRef refArg = PlusMinus( pGbl, pGbl, &p ); 325cdf0e10cSrcweir if( !refArg ) 326cdf0e10cSrcweir { 327cdf0e10cSrcweir // Fehler beim Parsing 328cdf0e10cSrcweir refVar.Clear(); break; 329cdf0e10cSrcweir } 330cdf0e10cSrcweir else 331cdf0e10cSrcweir { 332cdf0e10cSrcweir // Man kopiere den Parameter, damit 333cdf0e10cSrcweir // man den aktuellen Zustand hat (loest auch 334cdf0e10cSrcweir // den Aufruf per Zugriff aus) 335cdf0e10cSrcweir SbxVariable* pArg = refArg; 336cdf0e10cSrcweir refPar->Put( new SbxVariable( *pArg ), ++nArg ); 337cdf0e10cSrcweir } 338cdf0e10cSrcweir p = SkipWhitespace( p ); 339cdf0e10cSrcweir if( *p == ',' ) 340cdf0e10cSrcweir p++; 341cdf0e10cSrcweir } 342cdf0e10cSrcweir if( *p == ')' ) 343cdf0e10cSrcweir p++; 344cdf0e10cSrcweir if( refVar.Is() ) 345cdf0e10cSrcweir refVar->SetParameters( refPar ); 346cdf0e10cSrcweir } 347cdf0e10cSrcweir } 348cdf0e10cSrcweir else 349cdf0e10cSrcweir SbxBase::SetError( SbxERR_NO_METHOD ); 350cdf0e10cSrcweir } 351cdf0e10cSrcweir *ppBuf = p; 352cdf0e10cSrcweir if( refVar.Is() ) 353cdf0e10cSrcweir refVar->AddRef(); 354cdf0e10cSrcweir return refVar; 355cdf0e10cSrcweir } 356cdf0e10cSrcweir 357cdf0e10cSrcweir // Hauptroutine 358cdf0e10cSrcweir 359cdf0e10cSrcweir SbxVariable* SbxObject::Execute( const XubString& rTxt ) 360cdf0e10cSrcweir { 361cdf0e10cSrcweir SbxVariable* pVar = NULL; 362cdf0e10cSrcweir const xub_Unicode* p = rTxt.GetBuffer(); 363cdf0e10cSrcweir for( ;; ) 364cdf0e10cSrcweir { 365cdf0e10cSrcweir p = SkipWhitespace( p ); 366cdf0e10cSrcweir if( !*p ) 367cdf0e10cSrcweir break; 368cdf0e10cSrcweir if( *p++ != '[' ) 369cdf0e10cSrcweir { 370cdf0e10cSrcweir SetError( SbxERR_SYNTAX ); break; 371cdf0e10cSrcweir } 372cdf0e10cSrcweir pVar = Assign( this, this, &p ); 373cdf0e10cSrcweir if( !pVar ) 374cdf0e10cSrcweir break; 375cdf0e10cSrcweir p = SkipWhitespace( p ); 376cdf0e10cSrcweir if( *p++ != ']' ) 377cdf0e10cSrcweir { 378cdf0e10cSrcweir SetError( SbxERR_SYNTAX ); break; 379cdf0e10cSrcweir } 380cdf0e10cSrcweir } 381cdf0e10cSrcweir return pVar; 382cdf0e10cSrcweir } 383cdf0e10cSrcweir 384cdf0e10cSrcweir SbxVariable* SbxObject::FindQualified( const XubString& rName, SbxClassType t ) 385cdf0e10cSrcweir { 386cdf0e10cSrcweir SbxVariable* pVar = NULL; 387cdf0e10cSrcweir const xub_Unicode* p = rName.GetBuffer(); 388cdf0e10cSrcweir p = SkipWhitespace( p ); 389cdf0e10cSrcweir if( !*p ) 390*be099857Smseidel return NULL; 391cdf0e10cSrcweir pVar = QualifiedName( this, this, &p, t ); 392cdf0e10cSrcweir p = SkipWhitespace( p ); 393cdf0e10cSrcweir if( *p ) 394cdf0e10cSrcweir SetError( SbxERR_SYNTAX ); 395cdf0e10cSrcweir return pVar; 396cdf0e10cSrcweir } 397