1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <basic/sbx.hxx>
21 #include "sbunoobj.hxx"
23 #include <svtools/miscopt.hxx>
24 #include <osl/diagnose.h>
25 #include <com/sun/star/reflection/theCoreReflection.hpp>
26 #include <comphelper/namedvaluecollection.hxx>
27 #include <comphelper/processfactory.hxx>
28 #include <com/sun/star/reflection/XInterfaceMemberTypeDescription.hpp>
29 #include <com/sun/star/reflection/XIdlMethod.hpp>
30 #include <com/sun/star/uno/Exception.hpp>
31 #include <basic/codecompletecache.hxx>
34 using namespace ::com::sun::star
;
35 using namespace ::com::sun::star::uno
;
37 // Declaration of a variable
38 // If there are errors it will be parsed up to the comma or the newline.
39 // Return-value: a new instance, which were inserted and then deleted.
40 // Array-Index were returned as SbiExprList
42 SbiSymDef
* SbiParser::VarDecl( SbiExprListPtr
* ppDim
, bool bStatic
, bool bConst
)
44 bool bWithEvents
= false;
45 if( Peek() == WITHEVENTS
)
50 if( !TestSymbol() ) return nullptr;
51 SbxDataType t
= eScanType
;
52 SbiSymDef
* pDef
= bConst
? new SbiConstDef( aSym
) : new SbiSymDef( aSym
);
55 if( Peek() == LPAREN
)
57 pDim
= SbiExprList::ParseDimList( this );
58 if( !pDim
->GetDims() )
59 pDef
->SetWithBrackets();
65 pDef
->SetWithEvents();
70 Error( ERRCODE_BASIC_EXPECTED
, "()" );
73 *ppDim
= std::move(pDim
);
77 // Resolving of a AS-Type-Declaration
78 // The data type were inserted into the handed over variable
80 void SbiParser::TypeDecl( SbiSymDef
& rDef
, bool bAsNewAlreadyParsed
)
82 SbxDataType eType
= rDef
.GetType();
83 if( bAsNewAlreadyParsed
|| Peek() == AS
)
86 if( !bAsNewAlreadyParsed
)
89 SbiToken eTok
= Next();
90 if( !bAsNewAlreadyParsed
&& eTok
== NEW
)
99 Error( ERRCODE_BASIC_SYNTAX
);
100 eType
= SbxVARIANT
; break;
114 Error( ERRCODE_BASIC_SYNTAX
);
115 eType
= (eTok
==TBYTE
) ? SbxBYTE
: SbxDataType( eTok
- TINTEGER
+ SbxINTEGER
);
116 if( eType
== SbxSTRING
)
122 SbiConstExpression
aSize( this );
123 nSize
= aSize
.GetShortValue();
124 if( nSize
< 0 || (bVBASupportOn
&& nSize
<= 0) )
125 Error( ERRCODE_BASIC_OUT_OF_RANGE
);
127 rDef
.SetFixedStringLength( nSize
);
131 case SYMBOL
: // can only be a TYPE or a object class!
132 if( eScanType
!= SbxVARIANT
)
133 Error( ERRCODE_BASIC_SYNTAX
);
136 OUString aCompleteName
= aSym
;
138 // #52709 DIM AS NEW for Uno with full-qualified name
141 OUString
aDotStr( '.' );
142 while( Peek() == DOT
)
144 aCompleteName
+= aDotStr
;
146 SbiToken ePeekTok
= Peek();
147 if( ePeekTok
== SYMBOL
|| IsKwd( ePeekTok
) )
150 aCompleteName
+= aSym
;
155 Error( ERRCODE_BASIC_UNEXPECTED
, SYMBOL
);
160 else if( rEnumArray
->Find( aCompleteName
, SbxClassType::Object
) || ( IsVBASupportOn() && VBAConstantHelper::instance().isVBAConstantType( aCompleteName
) ) )
166 // Take over in the string pool
167 rDef
.SetTypeId( aGblStrings
.Add( aCompleteName
) );
169 if( rDef
.IsNew() && pProc
== nullptr )
170 aRequiredTypes
.push_back( aCompleteName
);
174 case FIXSTRING
: // new syntax for complex UNO types
175 rDef
.SetTypeId( aGblStrings
.Add( aSym
) );
179 Error( ERRCODE_BASIC_UNEXPECTED
, eTok
);
182 // The variable could have been declared with a suffix
183 if( rDef
.GetType() != SbxVARIANT
)
185 if( rDef
.GetType() != eType
)
186 Error( ERRCODE_BASIC_VAR_DEFINED
, rDef
.GetName() );
187 else if( eType
== SbxSTRING
&& rDef
.GetLen() != nSize
)
188 Error( ERRCODE_BASIC_VAR_DEFINED
, rDef
.GetName() );
190 rDef
.SetType( eType
);
191 rDef
.SetLen( nSize
);
195 // Here variables, arrays and structures were definied.
196 // DIM/PRIVATE/PUBLIC/GLOBAL
198 void SbiParser::Dim()
200 DefVar( SbiOpcode::DIM_
, pProc
&& bVBASupportOn
&& pProc
->IsStatic() );
203 void SbiParser::DefVar( SbiOpcode eOp
, bool bStatic
)
205 SbiSymPool
* pOldPool
= pPool
;
206 bool bSwitchPool
= false;
207 bool bPersistentGlobal
= false;
208 SbiToken eFirstTok
= eCurTok
;
210 if( pProc
&& ( eCurTok
== GLOBAL
|| eCurTok
== PUBLIC
|| eCurTok
== PRIVATE
) )
211 Error( ERRCODE_BASIC_NOT_IN_SUBR
, eCurTok
);
212 if( eCurTok
== PUBLIC
|| eCurTok
== GLOBAL
)
214 bSwitchPool
= true; // at the right moment switch to the global pool
215 if( eCurTok
== GLOBAL
)
216 bPersistentGlobal
= true;
218 // behavior in VBA is that a module scope variable's lifetime is
219 // tied to the document. e.g. a module scope variable is global
220 if( GetBasic()->IsDocBasic() && bVBASupportOn
&& !pProc
)
221 bPersistentGlobal
= true;
222 // PRIVATE is a synonymous for DIM
225 if( eCurTok
== CONST_
)
227 else if( Peek() == CONST_
)
233 // #110004 It can also be a sub/function
234 if( !bConst
&& (eCurTok
== SUB
|| eCurTok
== FUNCTION
|| eCurTok
== PROPERTY
||
235 eCurTok
== STATIC
|| eCurTok
== ENUM
|| eCurTok
== DECLARE
|| eCurTok
== TYPE
) )
237 // Next token is read here, because !bConst
238 bool bPrivate
= ( eFirstTok
== PRIVATE
);
240 if( eCurTok
== STATIC
)
243 DefStatic( bPrivate
);
245 else if( eCurTok
== SUB
|| eCurTok
== FUNCTION
|| eCurTok
== PROPERTY
)
247 // End global chain if necessary (not done in
248 // SbiParser::Parse() under these conditions
249 if( bNewGblDefs
&& nGblChain
== 0 )
251 nGblChain
= aGen
.Gen( SbiOpcode::JUMP_
, 0 );
255 DefProc( false, bPrivate
);
258 else if( eCurTok
== ENUM
)
264 else if( eCurTok
== DECLARE
)
267 DefDeclare( bPrivate
);
271 else if( eCurTok
== TYPE
)
279 // SHARED were ignored
280 if( Peek() == SHARED
) Next();
282 // PRESERVE only at REDIM
283 if( Peek() == PRESERVE
)
286 if( eOp
== SbiOpcode::REDIM_
)
287 eOp
= SbiOpcode::REDIMP_
;
289 Error( ERRCODE_BASIC_UNEXPECTED
, eCurTok
);
294 // #40689, Statics -> Module-Initialising, skip in Sub
295 sal_uInt32 nEndOfStaticLbl
= 0;
296 if( !bVBASupportOn
&& bStatic
)
298 nEndOfStaticLbl
= aGen
.Gen( SbiOpcode::JUMP_
, 0 );
299 aGen
.Statement(); // catch up on static here
302 bool bDefined
= false;
303 while( ( pDef
= VarDecl( &pDim
, bStatic
, bConst
) ) != nullptr )
305 /*fprintf(stderr, "Actual sub: \n");
306 fprintf(stderr, "Symbol name: %s\n",OUStringToOString(pDef->GetName(),RTL_TEXTENCODING_UTF8).getStr());*/
311 SbiSymDef
* pOld
= pPool
->Find( pDef
->GetName() );
312 // search also in the Runtime-Library
313 bool bRtlSym
= false;
316 pOld
= CheckRTLForSym( pDef
->GetName(), SbxVARIANT
);
320 if( pOld
&& !(eOp
== SbiOpcode::REDIM_
|| eOp
== SbiOpcode::REDIMP_
) )
322 if( pDef
->GetScope() == SbLOCAL
&& pOld
->GetScope() != SbLOCAL
)
328 // always an error at a RTL-S
329 if( !bRtlSym
&& (eOp
== SbiOpcode::REDIM_
|| eOp
== SbiOpcode::REDIMP_
) )
331 // compare the attributes at a REDIM
332 SbxDataType eDefType
;
333 bool bError_
= false;
334 if( pOld
->IsStatic() )
338 else if( pOld
->GetType() != ( eDefType
= pDef
->GetType() ) )
340 if( !( eDefType
== SbxVARIANT
&& !pDef
->IsDefinedAs() ) )
344 Error( ERRCODE_BASIC_VAR_DEFINED
, pDef
->GetName() );
347 Error( ERRCODE_BASIC_VAR_DEFINED
, pDef
->GetName() );
348 delete pDef
; pDef
= pOld
;
353 // #36374: Create the variable in front of the distinction IsNew()
354 // Otherwise error at Dim Identifier As New Type and option explicit
355 if( !bDefined
&& !(eOp
== SbiOpcode::REDIM_
|| eOp
== SbiOpcode::REDIMP_
)
356 && ( !bConst
|| pDef
->GetScope() == SbGLOBAL
) )
358 // Declare variable or global constant
360 switch ( pDef
->GetScope() )
362 case SbGLOBAL
: eOp2
= bPersistentGlobal
? SbiOpcode::GLOBAL_P_
: SbiOpcode::GLOBAL_
;
364 case SbPUBLIC
: eOp2
= bPersistentGlobal
? SbiOpcode::PUBLIC_P_
: SbiOpcode::PUBLIC_
;
365 // #40689, no own Opcode anymore
366 if( bVBASupportOn
&& bStatic
)
368 eOp2
= SbiOpcode::STATIC_
;
371 global
: aGen
.BackChain( nGblChain
);
373 bGblDefs
= bNewGblDefs
= true;
375 default: eOp2
= SbiOpcode::LOCAL_
;
377 sal_uInt32 nOpnd2
= sal::static_int_cast
< sal_uInt16
>( pDef
->GetType() );
378 if( pDef
->IsWithEvents() )
379 nOpnd2
|= SBX_TYPE_WITH_EVENTS_FLAG
;
381 if( bCompatible
&& pDef
->IsNew() )
382 nOpnd2
|= SBX_TYPE_DIM_AS_NEW_FLAG
;
384 short nFixedStringLength
= pDef
->GetFixedStringLength();
385 if( nFixedStringLength
>= 0 )
386 nOpnd2
|= (SBX_FIXED_LEN_STRING_FLAG
+ (sal_uInt32(nFixedStringLength
) << 17)); // len = all bits above 0x10000
388 if( pDim
!= nullptr && pDim
->GetDims() > 0 )
389 nOpnd2
|= SBX_TYPE_VAR_TO_DIM_FLAG
;
391 aGen
.Gen( eOp2
, pDef
->GetId(), nOpnd2
);
394 // Initialising for self-defined data types
395 // and per NEW created variable
396 if( pDef
->GetType() == SbxOBJECT
397 && pDef
->GetTypeId() )
399 if( !bCompatible
&& !pDef
->IsNew() )
401 OUString
aTypeName( aGblStrings
.Find( pDef
->GetTypeId() ) );
402 if( rTypeArray
->Find( aTypeName
, SbxClassType::Object
) == nullptr )
404 if( CodeCompleteOptions::IsExtendedTypeDeclaration() )
406 if(!IsUnoInterface(aTypeName
))
407 Error( ERRCODE_BASIC_UNDEF_TYPE
, aTypeName
);
410 Error( ERRCODE_BASIC_UNDEF_TYPE
, aTypeName
);
416 Error( ERRCODE_BASIC_SYNTAX
);
421 if( eOp
== SbiOpcode::REDIMP_
)
423 SbiExpression
aExpr( this, *pDef
, nullptr );
425 aGen
.Gen( SbiOpcode::REDIMP_ERASE_
);
427 pDef
->SetDims( pDim
->GetDims() );
428 SbiExpression
aExpr2( this, *pDef
, std::move(pDim
) );
430 aGen
.Gen( SbiOpcode::DCREATE_REDIMP_
, pDef
->GetId(), pDef
->GetTypeId() );
434 pDef
->SetDims( pDim
->GetDims() );
435 SbiExpression
aExpr( this, *pDef
, std::move(pDim
) );
437 aGen
.Gen( SbiOpcode::DCREATE_
, pDef
->GetId(), pDef
->GetTypeId() );
442 SbiExpression
aExpr( this, *pDef
);
444 SbiOpcode eOp_
= pDef
->IsNew() ? SbiOpcode::CREATE_
: SbiOpcode::TCREATE_
;
445 aGen
.Gen( eOp_
, pDef
->GetId(), pDef
->GetTypeId() );
447 aGen
.Gen( SbiOpcode::VBASET_
);
449 aGen
.Gen( SbiOpcode::SET_
);
456 // Definition of the constants
459 Error( ERRCODE_BASIC_SYNTAX
);
461 SbiExpression
aVar( this, *pDef
);
462 if( !TestToken( EQ
) )
463 goto MyBreak
; // (see below)
464 SbiConstExpression
aExpr( this );
465 if( !bDefined
&& aExpr
.IsValid() )
467 if( pDef
->GetScope() == SbGLOBAL
)
469 // Create code only for the global constant!
472 aGen
.Gen( SbiOpcode::PUTC_
);
474 SbiConstDef
* pConst
= pDef
->GetConstDef();
475 if( aExpr
.GetType() == SbxSTRING
)
476 pConst
->Set( aExpr
.GetString() );
478 pConst
->Set( aExpr
.GetValue(), aExpr
.GetType() );
483 // Dimension the variable
484 // Delete the var at REDIM beforehand
485 if( eOp
== SbiOpcode::REDIM_
)
487 SbiExpression
aExpr( this, *pDef
, nullptr );
490 // delete the array but
491 // clear the variable ( this
492 // allows the processing of
493 // the param to happen as normal without errors ( ordinary ERASE just clears the array )
494 aGen
.Gen( SbiOpcode::ERASE_CLEAR_
);
496 aGen
.Gen( SbiOpcode::ERASE_
);
498 else if( eOp
== SbiOpcode::REDIMP_
)
500 SbiExpression
aExpr( this, *pDef
, nullptr );
502 aGen
.Gen( SbiOpcode::REDIMP_ERASE_
);
504 pDef
->SetDims( pDim
->GetDims() );
505 if( bPersistentGlobal
)
506 pDef
->SetGlobal( true );
507 SbiExpression
aExpr( this, *pDef
, std::move(pDim
) );
509 pDef
->SetGlobal( false );
510 aGen
.Gen( (eOp
== SbiOpcode::STATIC_
) ? SbiOpcode::DIM_
: eOp
);
516 // Implementation of bSwitchPool (see above): pPool must not be set to &aGlobals
517 // at the VarDecl-Call.
518 // Apart from that the behavior should be absolutely identical,
519 // i.e., pPool had to be reset always at the end of the loop.
522 continue; // Skip MyBreak
528 // #40689, finalize the jump over statics declarations
529 if( !bVBASupportOn
&& bStatic
)
531 // maintain the global chain
532 nGblChain
= aGen
.Gen( SbiOpcode::JUMP_
, 0 );
533 bGblDefs
= bNewGblDefs
= true;
535 // Register for Sub a jump to the end of statics
536 aGen
.BackChain( nEndOfStaticLbl
);
541 // Here were Arrays redimensioned.
543 void SbiParser::ReDim()
545 DefVar( SbiOpcode::REDIM_
, pProc
&& bVBASupportOn
&& pProc
->IsStatic() );
550 void SbiParser::Erase()
554 SbiExpression
aExpr( this, SbLVALUE
);
556 aGen
.Gen( SbiOpcode::ERASE_
);
557 if( !TestComma() ) break;
561 // Declaration of a data type
563 void SbiParser::Type()
568 void SbiParser::DefType( bool bPrivate
)
570 // TODO: Use bPrivate
573 // Read the new Token lesen. It had to be a symbol
577 if (rTypeArray
->Find(aSym
,SbxClassType::Object
))
579 Error( ERRCODE_BASIC_VAR_DEFINED
, aSym
);
583 SbxObject
*pType
= new SbxObject(aSym
);
587 while( !bDone
&& !IsEof() )
589 std::unique_ptr
<SbiSymDef
> pElem
;
604 pElem
.reset(VarDecl(&pDim
, false, false));
606 bDone
= true; // Error occurred
610 SbxArray
*pTypeMembers
= pType
->GetProperties();
611 OUString aElemName
= pElem
->GetName();
612 if( pTypeMembers
->Find( aElemName
, SbxClassType::DontCare
) )
614 Error (ERRCODE_BASIC_VAR_DEFINED
);
618 SbxDataType eElemType
= pElem
->GetType();
619 SbxProperty
*pTypeElem
= new SbxProperty( aElemName
, eElemType
);
622 SbxDimArray
* pArray
= new SbxDimArray( pElem
->GetType() );
623 if ( pDim
->GetSize() )
625 // Dimension the target array
627 for ( short i
=0; i
<pDim
->GetSize();++i
)
629 sal_Int32 lb
= nBase
;
630 SbiExprNode
* pNode
= pDim
->Get(i
)->GetExprNode();
631 sal_Int32 ub
= pNode
->GetNumber();
632 if ( !pDim
->Get( i
)->IsBased() ) // each dim is low/up
634 if ( ++i
>= pDim
->GetSize() ) // trouble
635 StarBASIC::FatalError( ERRCODE_BASIC_INTERNAL_ERROR
);
636 pNode
= pDim
->Get(i
)->GetExprNode();
638 ub
= pNode
->GetNumber();
640 else if ( !bCompatible
)
642 pArray
->AddDim32( lb
, ub
);
644 pArray
->setHasFixedSize( true );
647 pArray
->unoAddDim( 0, -1 ); // variant array
648 SbxFlagBits nSavFlags
= pTypeElem
->GetFlags();
649 // need to reset the FIXED flag
650 // when calling PutObject ( because the type will not match Object )
651 pTypeElem
->ResetFlag( SbxFlagBits::Fixed
);
652 pTypeElem
->PutObject( pArray
);
653 pTypeElem
->SetFlags( nSavFlags
);
656 if( eElemType
== SbxOBJECT
)
658 sal_uInt16 nElemTypeId
= pElem
->GetTypeId();
659 if( nElemTypeId
!= 0 )
661 OUString
aTypeName( aGblStrings
.Find( nElemTypeId
) );
662 SbxObject
* pTypeObj
= static_cast< SbxObject
* >( rTypeArray
->Find( aTypeName
, SbxClassType::Object
) );
663 if( pTypeObj
!= nullptr )
665 SbxObject
* pCloneObj
= cloneTypeObjectImpl( *pTypeObj
);
666 pTypeElem
->PutObject( pCloneObj
);
670 pTypeMembers
->Insert( pTypeElem
, pTypeMembers
->Count() );
675 pType
->Remove( "Name", SbxClassType::DontCare
);
676 pType
->Remove( "Parent", SbxClassType::DontCare
);
678 rTypeArray
->Insert (pType
,rTypeArray
->Count());
682 // Declaration of Enum type
684 void SbiParser::Enum()
689 void SbiParser::DefEnum( bool bPrivate
)
691 // Read a the new Token. It had to be a symbol
695 OUString aEnumName
= aSym
;
696 if( rEnumArray
->Find(aEnumName
,SbxClassType::Object
) )
698 Error( ERRCODE_BASIC_VAR_DEFINED
, aSym
);
702 SbxObject
*pEnum
= new SbxObject( aEnumName
);
705 pEnum
->SetFlag( SbxFlagBits::Private
);
710 // Starting with -1 to make first default value 0 after ++
711 sal_Int32 nCurrentEnumValue
= -1;
712 while( !bDone
&& !IsEof() )
731 pElem
= VarDecl( &pDim
, false, true );
734 bDone
= true; // Error occurred
739 Error( ERRCODE_BASIC_SYNTAX
);
740 bDone
= true; // Error occurred
744 SbiExpression
aVar( this, *pElem
);
749 SbiConstExpression
aExpr( this );
750 if( aExpr
.IsValid() )
752 SbxVariableRef xConvertVar
= new SbxVariable();
753 if( aExpr
.GetType() == SbxSTRING
)
754 xConvertVar
->PutString( aExpr
.GetString() );
756 xConvertVar
->PutDouble( aExpr
.GetValue() );
758 nCurrentEnumValue
= xConvertVar
->GetLong();
764 SbiSymPool
* pPoolToUse
= bPrivate
? pPool
: &aGlobals
;
766 SbiSymDef
* pOld
= pPoolToUse
->Find( pElem
->GetName() );
769 Error( ERRCODE_BASIC_VAR_DEFINED
, pElem
->GetName() );
770 bDone
= true; // Error occurred
778 SbiOpcode eOp
= SbiOpcode::GLOBAL_
;
779 aGen
.BackChain( nGblChain
);
781 bGblDefs
= bNewGblDefs
= true;
784 sal::static_int_cast
< sal_uInt16
>( pElem
->GetType() ) );
787 sal_uInt16 nStringId
= aGen
.GetParser()->aGblStrings
.Add( nCurrentEnumValue
, SbxLONG
);
788 aGen
.Gen( SbiOpcode::NUMBER_
, nStringId
);
789 aGen
.Gen( SbiOpcode::PUTC_
);
792 SbiConstDef
* pConst
= pElem
->GetConstDef();
793 pConst
->Set( nCurrentEnumValue
, SbxLONG
);
798 SbxArray
*pEnumMembers
= pEnum
->GetProperties();
799 SbxProperty
*pEnumElem
= new SbxProperty( pElem
->GetName(), SbxLONG
);
800 pEnumElem
->PutLong( nCurrentEnumValue
);
801 pEnumElem
->ResetFlag( SbxFlagBits::Write
);
802 pEnumElem
->SetFlag( SbxFlagBits::Const
);
803 pEnumMembers
->Insert( pEnumElem
, pEnumMembers
->Count() );
807 pEnum
->Remove( "Name", SbxClassType::DontCare
);
808 pEnum
->Remove( "Parent", SbxClassType::DontCare
);
810 rEnumArray
->Insert( pEnum
, rEnumArray
->Count() );
814 // Procedure-Declaration
815 // the first Token is already read in (SUB/FUNCTION)
816 // xxx Name [LIB "name"[ALIAS "name"]][(Parameter)][AS TYPE]
818 SbiProcDef
* SbiParser::ProcDecl( bool bDecl
)
820 bool bFunc
= ( eCurTok
== FUNCTION
);
821 bool bProp
= ( eCurTok
== GET
|| eCurTok
== SET
|| eCurTok
== LET
);
822 if( !TestSymbol() ) return nullptr;
823 OUString
aName( aSym
);
824 SbxDataType eType
= eScanType
;
825 SbiProcDef
* pDef
= new SbiProcDef( this, aName
, true );
826 pDef
->SetType( eType
);
827 if( Peek() == CDECL_
)
829 Next(); pDef
->SetCdecl(true);
834 if( Next() == FIXSTRING
)
836 pDef
->GetLib() = aSym
;
840 Error( ERRCODE_BASIC_SYNTAX
);
843 if( Peek() == ALIAS
)
846 if( Next() == FIXSTRING
)
848 pDef
->GetAlias() = aSym
;
852 Error( ERRCODE_BASIC_SYNTAX
);
857 // CDECL, LIB and ALIAS are invalid
858 if( !pDef
->GetLib().isEmpty() )
860 Error( ERRCODE_BASIC_UNEXPECTED
, LIB
);
862 if( !pDef
->GetAlias().isEmpty() )
864 Error( ERRCODE_BASIC_UNEXPECTED
, ALIAS
);
866 if( pDef
->IsCdecl() )
868 Error( ERRCODE_BASIC_UNEXPECTED
, CDECL_
);
870 pDef
->SetCdecl( false );
871 pDef
->GetLib().clear();
872 pDef
->GetAlias().clear();
874 else if( pDef
->GetLib().isEmpty() )
876 // ALIAS and CDECL only together with LIB
877 if( !pDef
->GetAlias().isEmpty() )
879 Error( ERRCODE_BASIC_UNEXPECTED
, ALIAS
);
881 if( pDef
->IsCdecl() )
883 Error( ERRCODE_BASIC_UNEXPECTED
, CDECL_
);
885 pDef
->SetCdecl( false );
886 pDef
->GetAlias().clear();
889 if( Peek() == LPAREN
)
892 if( Peek() == RPAREN
)
901 bool bOptional
= false;
902 bool bParamArray
= false;
903 while( Peek() == BYVAL
|| Peek() == BYREF
|| Peek() == OPTIONAL_
)
905 if( Peek() == BYVAL
)
909 else if ( Peek() == BYREF
)
913 else if ( Peek() == OPTIONAL_
)
919 if( bCompatible
&& Peek() == PARAMARRAY
)
921 if( bByVal
|| bOptional
)
923 Error( ERRCODE_BASIC_UNEXPECTED
, PARAMARRAY
);
928 SbiSymDef
* pPar
= VarDecl( nullptr, false, false );
935 pPar
->SetByVal(true);
943 pPar
->SetParamArray();
945 pDef
->GetParams().Add( pPar
);
946 SbiToken eTok
= Next();
947 if( eTok
!= COMMA
&& eTok
!= RPAREN
)
950 if( bOptional
&& bCompatible
&& eTok
== EQ
)
952 std::unique_ptr
<SbiConstExpression
> pDefaultExpr(new SbiConstExpression( this ));
953 SbxDataType eType2
= pDefaultExpr
->GetType();
955 sal_uInt16 nStringId
;
956 if( eType2
== SbxSTRING
)
958 nStringId
= aGblStrings
.Add( pDefaultExpr
->GetString() );
962 nStringId
= aGblStrings
.Add( pDefaultExpr
->GetValue(), eType2
);
964 pPar
->SetDefaultId( nStringId
);
965 pDefaultExpr
.reset();
968 if( eTok
== COMMA
|| eTok
== RPAREN
)
975 Error( ERRCODE_BASIC_EXPECTED
, RPAREN
);
987 if( eType
!= SbxVARIANT
&& pDef
->GetType() != eType
)
989 Error( ERRCODE_BASIC_BAD_DECLARATION
, aName
);
991 if( pDef
->GetType() == SbxVARIANT
&& !( bFunc
|| bProp
) )
993 pDef
->SetType( SbxEMPTY
);
1000 void SbiParser::Declare()
1002 DefDeclare( false );
1005 void SbiParser::DefDeclare( bool bPrivate
)
1008 if( eCurTok
== PTRSAFE
)
1011 if( eCurTok
!= SUB
&& eCurTok
!= FUNCTION
)
1013 Error( ERRCODE_BASIC_UNEXPECTED
, eCurTok
);
1017 bool bFunction
= (eCurTok
== FUNCTION
);
1019 SbiProcDef
* pDef
= ProcDecl( true );
1022 if( pDef
->GetLib().isEmpty() )
1024 Error( ERRCODE_BASIC_EXPECTED
, LIB
);
1026 // Is it already there?
1027 SbiSymDef
* pOld
= aPublics
.Find( pDef
->GetName() );
1030 SbiProcDef
* p
= pOld
->GetProcDef();
1033 // Declared as a variable
1034 Error( ERRCODE_BASIC_BAD_DECLARATION
, pDef
->GetName() );
1045 aPublics
.Add( pDef
);
1049 pDef
->SetPublic( !bPrivate
);
1051 // New declare handling
1052 if( !pDef
->GetLib().isEmpty())
1054 if( bNewGblDefs
&& nGblChain
== 0 )
1056 nGblChain
= aGen
.Gen( SbiOpcode::JUMP_
, 0 );
1057 bNewGblDefs
= false;
1060 sal_uInt16 nSavLine
= nLine
;
1063 pDef
->SetLine1( nSavLine
);
1064 pDef
->SetLine2( nSavLine
);
1066 SbiSymPool
& rPool
= pDef
->GetParams();
1067 sal_uInt16 nParCount
= rPool
.GetSize();
1069 SbxDataType eType
= pDef
->GetType();
1072 aGen
.Gen( SbiOpcode::PARAM_
, 0, sal::static_int_cast
< sal_uInt16
>( eType
) );
1076 aGen
.Gen( SbiOpcode::ARGC_
);
1078 for( sal_uInt16 i
= 1 ; i
< nParCount
; ++i
)
1080 SbiSymDef
* pParDef
= rPool
.Get( i
);
1081 SbxDataType eParType
= pParDef
->GetType();
1083 aGen
.Gen( SbiOpcode::PARAM_
, i
, sal::static_int_cast
< sal_uInt16
>( eParType
) );
1084 aGen
.Gen( SbiOpcode::ARGV_
);
1086 sal_uInt16 nTyp
= sal::static_int_cast
< sal_uInt16
>( pParDef
->GetType() );
1087 if( pParDef
->IsByVal() )
1089 // Reset to avoid additional byval in call to wrapper function
1090 pParDef
->SetByVal( false );
1093 aGen
.Gen( SbiOpcode::ARGTYP_
, nTyp
);
1097 aGen
.Gen( SbiOpcode::LIB_
, aGblStrings
.Add( pDef
->GetLib() ) );
1099 SbiOpcode eOp
= pDef
->IsCdecl() ? SbiOpcode::CALLC_
: SbiOpcode::CALL_
;
1100 sal_uInt16 nId
= pDef
->GetId();
1101 if( !pDef
->GetAlias().isEmpty() )
1103 nId
= ( nId
& 0x8000 ) | aGblStrings
.Add( pDef
->GetAlias() );
1109 aGen
.Gen( eOp
, nId
, sal::static_int_cast
< sal_uInt16
>( eType
) );
1113 aGen
.Gen( SbiOpcode::PUT_
);
1115 aGen
.Gen( SbiOpcode::LEAVE_
);
1122 void SbiParser::Attribute()
1124 // TODO: Need to implement the method as an attributed object.
1125 while( Next() != EQ
)
1135 Error( ERRCODE_BASIC_SYNTAX
);
1139 SbiExpression
aValue( this );
1141 // Don't generate any code - just discard it.
1144 // Call of a SUB or a FUNCTION
1146 void SbiParser::Call()
1148 SbiExpression
aVar( this, SbSYMBOL
);
1149 aVar
.Gen( FORCE_CALL
);
1150 aGen
.Gen( SbiOpcode::GET_
);
1155 void SbiParser::SubFunc()
1157 DefProc( false, false );
1160 // Read in of a procedure
1162 void SbiParser::DefProc( bool bStatic
, bool bPrivate
)
1164 sal_uInt16 l1
= nLine
;
1165 bool bSub
= ( eCurTok
== SUB
);
1166 bool bProperty
= ( eCurTok
== PROPERTY
);
1167 PropertyMode ePropertyMode
= PropertyMode::NONE
;
1171 if( eCurTok
== GET
)
1173 ePropertyMode
= PropertyMode::Get
;
1175 else if( eCurTok
== LET
)
1177 ePropertyMode
= PropertyMode::Let
;
1179 else if( eCurTok
== SET
)
1181 ePropertyMode
= PropertyMode::Set
;
1185 Error( ERRCODE_BASIC_EXPECTED
, "Get or Let or Set" );
1189 SbiToken eExit
= eCurTok
;
1190 SbiProcDef
* pDef
= ProcDecl( false );
1195 pDef
->setPropertyMode( ePropertyMode
);
1197 // Is the Proc already declared?
1198 SbiSymDef
* pOld
= aPublics
.Find( pDef
->GetName() );
1201 pProc
= pOld
->GetProcDef();
1204 // Declared as a variable
1205 Error( ERRCODE_BASIC_BAD_DECLARATION
, pDef
->GetName() );
1209 // #100027: Multiple declaration -> Error
1210 // #112787: Not for setup, REMOVE for 8
1211 else if( pProc
->IsUsedForProcDecl() )
1213 PropertyMode ePropMode
= pDef
->getPropertyMode();
1214 if( ePropMode
== PropertyMode::NONE
|| ePropMode
== pProc
->getPropertyMode() )
1216 Error( ERRCODE_BASIC_PROC_DEFINED
, pDef
->GetName() );
1222 pDef
->Match( pProc
);
1227 aPublics
.Add( pDef
);
1234 pProc
->SetPublic( !bPrivate
);
1236 // Now we set the search hierarchy for symbols as well as the
1237 // current procedure.
1238 aPublics
.SetProcId( pProc
->GetId() );
1239 pProc
->GetParams().SetParent( &aPublics
);
1242 if ( bVBASupportOn
)
1248 Error( ERRCODE_BASIC_NOT_IMPLEMENTED
); // STATIC SUB ...
1253 pProc
->SetStatic( false );
1255 // Normal case: Local variable->parameter->global variable
1256 pProc
->GetLocals().SetParent( &pProc
->GetParams() );
1257 pPool
= &pProc
->GetLocals();
1261 StmntBlock( bSub
? ENDSUB
: (bProperty
? ENDPROPERTY
: ENDFUNC
) );
1262 sal_uInt16 l2
= nLine
;
1263 pProc
->SetLine1( l1
);
1264 pProc
->SetLine2( l2
);
1266 aPublics
.SetProcId( 0 );
1268 pProc
->GetLabels().CheckRefs();
1270 aGen
.Gen( SbiOpcode::LEAVE_
);
1274 // STATIC variable|procedure
1276 void SbiParser::Static()
1281 void SbiParser::DefStatic( bool bPrivate
)
1290 // End global chain if necessary (not done in
1291 // SbiParser::Parse() under these conditions
1292 if( bNewGblDefs
&& nGblChain
== 0 )
1294 nGblChain
= aGen
.Gen( SbiOpcode::JUMP_
, 0 );
1295 bNewGblDefs
= false;
1298 DefProc( true, bPrivate
);
1303 Error( ERRCODE_BASIC_NOT_IN_SUBR
);
1305 // Reset the Pool, so that STATIC-Declarations go into the
1309 DefVar( SbiOpcode::STATIC_
, true );
1315 bool SbiParser::IsUnoInterface(const OUString
& sTypeName
)
1319 return css::reflection::theCoreReflection::get(
1320 comphelper::getProcessComponentContext())->forName(sTypeName
).is();
1322 catch(const Exception
&)
1324 OSL_FAIL("Could not create reflection.CoreReflection.");
1329 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */