bump product version to 5.0.4.1
[LibreOffice.git] / basic / source / comp / dim.cxx
blobe0366f88e0897e99202fe8e7554862fe79a0d082
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
22 #include "parser.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>
32 #include <boost/scoped_ptr.hpp>
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-Indexex were returned as SbiDimList
42 SbiSymDef* SbiParser::VarDecl( SbiDimList** ppDim, bool bStatic, bool bConst )
44 bool bWithEvents = false;
45 if( Peek() == WITHEVENTS )
47 Next();
48 bWithEvents = true;
50 if( !TestSymbol() ) return NULL;
51 SbxDataType t = eScanType;
52 SbiSymDef* pDef = bConst ? new SbiConstDef( aSym ) : new SbiSymDef( aSym );
53 SbiDimList* pDim = NULL;
54 // Brackets?
55 if( Peek() == LPAREN )
57 pDim = new SbiDimList( this );
58 if( !pDim->GetDims() )
59 pDef->SetWithBrackets();
61 pDef->SetType( t );
62 if( bStatic )
63 pDef->SetStatic();
64 if( bWithEvents )
65 pDef->SetWithEvents();
66 TypeDecl( *pDef );
67 if( !ppDim && pDim )
69 if(pDim->GetDims() )
70 Error( SbERR_EXPECTED, "()" );
71 delete pDim;
73 else if( ppDim )
74 *ppDim = pDim;
75 return pDef;
78 // Resolving of a AS-Type-Declaration
79 // The data type were inserted into the handed over variable
81 void SbiParser::TypeDecl( SbiSymDef& rDef, bool bAsNewAlreadyParsed )
83 SbxDataType eType = rDef.GetType();
84 if( bAsNewAlreadyParsed || Peek() == AS )
86 short nSize = 0;
87 if( !bAsNewAlreadyParsed )
88 Next();
89 rDef.SetDefinedAs();
90 SbiToken eTok = Next();
91 if( !bAsNewAlreadyParsed && eTok == NEW )
93 rDef.SetNew();
94 eTok = Next();
96 switch( eTok )
98 case ANY:
99 if( rDef.IsNew() )
100 Error( SbERR_SYNTAX );
101 eType = SbxVARIANT; break;
102 case TINTEGER:
103 case TLONG:
104 case TSINGLE:
105 case TDOUBLE:
106 case TCURRENCY:
107 case TDATE:
108 case TSTRING:
109 case TOBJECT:
110 case _ERROR_:
111 case TBOOLEAN:
112 case TVARIANT:
113 case TBYTE:
114 if( rDef.IsNew() )
115 Error( SbERR_SYNTAX );
116 eType = (eTok==TBYTE) ? SbxBYTE : SbxDataType( eTok - TINTEGER + SbxINTEGER );
117 if( eType == SbxSTRING )
119 // STRING*n ?
120 if( Peek() == MUL )
121 { // fixed size!
122 Next();
123 SbiConstExpression aSize( this );
124 nSize = aSize.GetShortValue();
125 if( nSize < 0 || (bVBASupportOn && nSize <= 0) )
126 Error( SbERR_OUT_OF_RANGE );
127 else
128 rDef.SetFixedStringLength( nSize );
131 break;
132 case SYMBOL: // can only be a TYPE or a object class!
133 if( eScanType != SbxVARIANT )
134 Error( SbERR_SYNTAX );
135 else
137 OUString aCompleteName = aSym;
139 // #52709 DIM AS NEW for Uno with full-qualified name
140 if( Peek() == DOT )
142 OUString aDotStr( '.' );
143 while( Peek() == DOT )
145 aCompleteName += aDotStr;
146 Next();
147 SbiToken ePeekTok = Peek();
148 if( ePeekTok == SYMBOL || IsKwd( ePeekTok ) )
150 Next();
151 aCompleteName += aSym;
153 else
155 Next();
156 Error( SbERR_UNEXPECTED, SYMBOL );
157 break;
161 else if( rEnumArray->Find( aCompleteName, SbxCLASS_OBJECT ) || ( IsVBASupportOn() && VBAConstantHelper::instance().isVBAConstantType( aCompleteName ) ) )
163 eType = SbxLONG;
164 break;
167 // Take over in the string pool
168 rDef.SetTypeId( aGblStrings.Add( aCompleteName ) );
170 if( rDef.IsNew() && pProc == NULL )
171 aRequiredTypes.push_back( aCompleteName );
173 eType = SbxOBJECT;
174 break;
175 case FIXSTRING: // new syntax for complex UNO types
176 rDef.SetTypeId( aGblStrings.Add( aSym ) );
177 eType = SbxOBJECT;
178 break;
179 default:
180 Error( SbERR_UNEXPECTED, eTok );
181 Next();
183 // The variable could have been declared with a suffix
184 if( rDef.GetType() != SbxVARIANT )
186 if( rDef.GetType() != eType )
187 Error( SbERR_VAR_DEFINED, rDef.GetName() );
188 else if( eType == SbxSTRING && rDef.GetLen() != nSize )
189 Error( SbERR_VAR_DEFINED, rDef.GetName() );
191 rDef.SetType( eType );
192 rDef.SetLen( nSize );
196 // Here variables, arrays and structures were definied.
197 // DIM/PRIVATE/PUBLIC/GLOBAL
199 void SbiParser::Dim()
201 DefVar( _DIM, pProc && bVBASupportOn && pProc->IsStatic() );
204 void SbiParser::DefVar( SbiOpcode eOp, bool bStatic )
206 SbiSymPool* pOldPool = pPool;
207 bool bSwitchPool = false;
208 bool bPersistantGlobal = false;
209 SbiToken eFirstTok = eCurTok;
211 if( pProc && ( eCurTok == GLOBAL || eCurTok == PUBLIC || eCurTok == PRIVATE ) )
212 Error( SbERR_NOT_IN_SUBR, eCurTok );
213 if( eCurTok == PUBLIC || eCurTok == GLOBAL )
215 bSwitchPool = true; // at the right moment switch to the global pool
216 if( eCurTok == GLOBAL )
217 bPersistantGlobal = true;
219 // behavior in VBA is that a module scope variable's lifetime is
220 // tied to the document. e.g. a module scope variable is global
221 if( GetBasic()->IsDocBasic() && bVBASupportOn && !pProc )
222 bPersistantGlobal = true;
223 // PRIVATE is a synonymous for DIM
224 // _CONST_?
225 bool bConst = false;
226 if( eCurTok == _CONST_ )
227 bConst = true;
228 else if( Peek() == _CONST_ )
229 Next(), bConst = true;
231 // #110004 It can also be a sub/function
232 if( !bConst && (eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY ||
233 eCurTok == STATIC || eCurTok == ENUM || eCurTok == DECLARE || eCurTok == TYPE) )
235 // Next token is read here, because !bConst
236 bool bPrivate = ( eFirstTok == PRIVATE );
238 if( eCurTok == STATIC )
240 Next();
241 DefStatic( bPrivate );
243 else if( eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY )
245 // End global chain if necessary (not done in
246 // SbiParser::Parse() under these conditions
247 if( bNewGblDefs && nGblChain == 0 )
249 nGblChain = aGen.Gen( _JUMP, 0 );
250 bNewGblDefs = false;
252 Next();
253 DefProc( false, bPrivate );
254 return;
256 else if( eCurTok == ENUM )
258 Next();
259 DefEnum( bPrivate );
260 return;
262 else if( eCurTok == DECLARE )
264 Next();
265 DefDeclare( bPrivate );
266 return;
268 // #i109049
269 else if( eCurTok == TYPE )
271 Next();
272 DefType( bPrivate );
273 return;
277 #ifdef SHARED
278 #define tmpSHARED
279 #undef SHARED
280 #endif
281 // SHARED were ignored
282 if( Peek() == SHARED ) Next();
283 #ifdef tmpSHARED
284 #define SHARED
285 #undef tmpSHARED
286 #endif
287 // PRESERVE only at REDIM
288 if( Peek() == PRESERVE )
290 Next();
291 if( eOp == _REDIM )
292 eOp = _REDIMP;
293 else
294 Error( SbERR_UNEXPECTED, eCurTok );
296 SbiSymDef* pDef;
297 SbiDimList* pDim;
299 // #40689, Statics -> Modul-Initialising, skip in Sub
300 sal_uInt32 nEndOfStaticLbl = 0;
301 if( !bVBASupportOn && bStatic )
303 nEndOfStaticLbl = aGen.Gen( _JUMP, 0 );
304 aGen.Statement(); // catch up on static here
307 bool bDefined = false;
308 while( ( pDef = VarDecl( &pDim, bStatic, bConst ) ) != NULL )
310 /*fprintf(stderr, "Actual sub: \n");
311 fprintf(stderr, "Symbol name: %s\n",OUStringToOString(pDef->GetName(),RTL_TEXTENCODING_UTF8).getStr());*/
312 EnableErrors();
313 // search variable:
314 if( bSwitchPool )
315 pPool = &aGlobals;
316 SbiSymDef* pOld = pPool->Find( pDef->GetName() );
317 // search also in the Runtime-Library
318 bool bRtlSym = false;
319 if( !pOld )
321 pOld = CheckRTLForSym( pDef->GetName(), SbxVARIANT );
322 if( pOld )
323 bRtlSym = true;
325 if( pOld && !(eOp == _REDIM || eOp == _REDIMP) )
327 if( pDef->GetScope() == SbLOCAL && pOld->GetScope() != SbLOCAL )
328 pOld = NULL;
330 if( pOld )
332 bDefined = true;
333 // always an error at a RTL-S
334 if( !bRtlSym && (eOp == _REDIM || eOp == _REDIMP) )
336 // compare the attributes at a REDIM
337 SbxDataType eDefType;
338 bool bError_ = false;
339 if( pOld->IsStatic() )
341 bError_ = true;
343 else if( pOld->GetType() != ( eDefType = pDef->GetType() ) )
345 if( !( eDefType == SbxVARIANT && !pDef->IsDefinedAs() ) )
346 bError_ = true;
348 if( bError_ )
349 Error( SbERR_VAR_DEFINED, pDef->GetName() );
351 else
352 Error( SbERR_VAR_DEFINED, pDef->GetName() );
353 delete pDef; pDef = pOld;
355 else
356 pPool->Add( pDef );
358 // #36374: Create the variable in front of the distinction IsNew()
359 // Otherwise error at Dim Identifier As New Type and option explicit
360 if( !bDefined && !(eOp == _REDIM || eOp == _REDIMP)
361 && ( !bConst || pDef->GetScope() == SbGLOBAL ) )
363 // Declare variable or global constant
364 SbiOpcode eOp2;
365 switch ( pDef->GetScope() )
367 case SbGLOBAL: eOp2 = bPersistantGlobal ? _GLOBAL_P : _GLOBAL;
368 goto global;
369 case SbPUBLIC: eOp2 = bPersistantGlobal ? _PUBLIC_P : _PUBLIC;
370 // #40689, no own Opcode anymore
371 if( bVBASupportOn && bStatic )
373 eOp2 = _STATIC;
374 break;
376 global: aGen.BackChain( nGblChain );
377 nGblChain = 0;
378 bGblDefs = bNewGblDefs = true;
379 break;
380 default: eOp2 = _LOCAL;
382 sal_uInt32 nOpnd2 = sal::static_int_cast< sal_uInt16 >( pDef->GetType() );
383 if( pDef->IsWithEvents() )
384 nOpnd2 |= SBX_TYPE_WITH_EVENTS_FLAG;
386 if( bCompatible && pDef->IsNew() )
387 nOpnd2 |= SBX_TYPE_DIM_AS_NEW_FLAG;
389 short nFixedStringLength = pDef->GetFixedStringLength();
390 if( nFixedStringLength >= 0 )
391 nOpnd2 |= (SBX_FIXED_LEN_STRING_FLAG + (sal_uInt32(nFixedStringLength) << 17)); // len = all bits above 0x10000
393 if( pDim != NULL && pDim->GetDims() > 0 )
394 nOpnd2 |= SBX_TYPE_VAR_TO_DIM_FLAG;
396 aGen.Gen( eOp2, pDef->GetId(), nOpnd2 );
399 // Initialising for self-defined daty types
400 // and per NEW created variable
401 if( pDef->GetType() == SbxOBJECT
402 && pDef->GetTypeId() )
404 if( !bCompatible && !pDef->IsNew() )
406 OUString aTypeName( aGblStrings.Find( pDef->GetTypeId() ) );
407 if( rTypeArray->Find( aTypeName, SbxCLASS_OBJECT ) == NULL )
409 if( CodeCompleteOptions::IsExtendedTypeDeclaration() )
411 if(!IsUnoInterface(aTypeName))
412 Error( SbERR_UNDEF_TYPE, aTypeName );
414 else
415 Error( SbERR_UNDEF_TYPE, aTypeName );
419 if( bConst )
421 Error( SbERR_SYNTAX );
424 if( pDim )
426 if( eOp == _REDIMP )
428 SbiExpression aExpr( this, *pDef, NULL );
429 aExpr.Gen();
430 aGen.Gen( _REDIMP_ERASE );
432 pDef->SetDims( pDim->GetDims() );
433 SbiExpression aExpr2( this, *pDef, pDim );
434 aExpr2.Gen();
435 aGen.Gen( _DCREATE_REDIMP, pDef->GetId(), pDef->GetTypeId() );
437 else
439 pDef->SetDims( pDim->GetDims() );
440 SbiExpression aExpr( this, *pDef, pDim );
441 aExpr.Gen();
442 aGen.Gen( _DCREATE, pDef->GetId(), pDef->GetTypeId() );
445 else
447 SbiExpression aExpr( this, *pDef );
448 aExpr.Gen();
449 SbiOpcode eOp_ = pDef->IsNew() ? _CREATE : _TCREATE;
450 aGen.Gen( eOp_, pDef->GetId(), pDef->GetTypeId() );
451 if ( bVBASupportOn )
452 aGen.Gen( _VBASET );
453 else
454 aGen.Gen( _SET );
457 else
459 if( bConst )
461 // Definition of the constants
462 if( pDim )
464 Error( SbERR_SYNTAX );
465 delete pDim;
467 SbiExpression aVar( this, *pDef );
468 if( !TestToken( EQ ) )
469 goto MyBreak; // (see below)
470 SbiConstExpression aExpr( this );
471 if( !bDefined && aExpr.IsValid() )
473 if( pDef->GetScope() == SbGLOBAL )
475 // Create code only for the global constant!
476 aVar.Gen();
477 aExpr.Gen();
478 aGen.Gen( _PUTC );
480 SbiConstDef* pConst = pDef->GetConstDef();
481 if( aExpr.GetType() == SbxSTRING )
482 pConst->Set( aExpr.GetString() );
483 else
484 pConst->Set( aExpr.GetValue(), aExpr.GetType() );
487 else if( pDim )
489 // Dimension the variable
490 // Delete the var at REDIM beforehand
491 if( eOp == _REDIM )
493 SbiExpression aExpr( this, *pDef, NULL );
494 aExpr.Gen();
495 if ( bVBASupportOn )
496 // delete the array but
497 // clear the variable ( this
498 // allows the processing of
499 // the param to happen as normal without errors ( ordinary ERASE just clears the array )
500 aGen.Gen( _ERASE_CLEAR );
501 else
502 aGen.Gen( _ERASE );
504 else if( eOp == _REDIMP )
506 SbiExpression aExpr( this, *pDef, NULL );
507 aExpr.Gen();
508 aGen.Gen( _REDIMP_ERASE );
510 pDef->SetDims( pDim->GetDims() );
511 if( bPersistantGlobal )
512 pDef->SetGlobal( true );
513 SbiExpression aExpr( this, *pDef, pDim );
514 aExpr.Gen();
515 pDef->SetGlobal( false );
516 aGen.Gen( (eOp == _STATIC) ? _DIM : eOp );
519 if( !TestComma() )
520 goto MyBreak;
522 // Implementation of bSwitchPool (see above): pPool must not be set to &aGlobals
523 // at the VarDecl-Call.
524 // Apart from that the behavior should be absolutely identical,
525 // i.e., pPool had to be reset always at the end of the loop.
526 // also at a break
527 pPool = pOldPool;
528 continue; // Skip MyBreak
529 MyBreak:
530 pPool = pOldPool;
531 break;
534 // #40689, finalize the jump over statics declarations
535 if( !bVBASupportOn && bStatic )
537 // maintain the global chain
538 nGblChain = aGen.Gen( _JUMP, 0 );
539 bGblDefs = bNewGblDefs = true;
541 // Register for Sub a jump to the end of statics
542 aGen.BackChain( nEndOfStaticLbl );
547 // Here were Arrays redimensioned.
549 void SbiParser::ReDim()
551 DefVar( _REDIM, pProc && bVBASupportOn && pProc->IsStatic() );
554 // ERASE array, ...
556 void SbiParser::Erase()
558 while( !bAbort )
560 SbiExpression aExpr( this, SbLVALUE );
561 aExpr.Gen();
562 aGen.Gen( _ERASE );
563 if( !TestComma() ) break;
567 // Declaration of a data type
569 void SbiParser::Type()
571 DefType( false );
574 void SbiParser::DefType( bool bPrivate )
576 // TODO: Use bPrivate
577 (void)bPrivate;
579 // Read the new Token lesen. It had to be a symbol
580 if (!TestSymbol())
581 return;
583 if (rTypeArray->Find(aSym,SbxCLASS_OBJECT))
585 Error( SbERR_VAR_DEFINED, aSym );
586 return;
589 SbxObject *pType = new SbxObject(aSym);
591 boost::scoped_ptr<SbiSymDef> pElem;
592 SbiDimList* pDim = NULL;
593 bool bDone = false;
595 while( !bDone && !IsEof() )
597 switch( Peek() )
599 case ENDTYPE :
600 bDone = true;
601 Next();
602 break;
604 case EOLN :
605 case REM :
606 Next();
607 break;
609 default:
610 pElem.reset(VarDecl(&pDim, false, false));
611 if( !pElem )
612 bDone = true; // Error occurred
614 if( pElem )
616 SbxArray *pTypeMembers = pType->GetProperties();
617 OUString aElemName = pElem->GetName();
618 if( pTypeMembers->Find( aElemName, SbxCLASS_DONTCARE) )
620 Error (SbERR_VAR_DEFINED);
622 else
624 SbxDataType eElemType = pElem->GetType();
625 SbxProperty *pTypeElem = new SbxProperty( aElemName, eElemType );
626 if( pDim )
628 SbxDimArray* pArray = new SbxDimArray( pElem->GetType() );
629 if ( pDim->GetSize() )
631 // Dimension the target array
633 for ( short i=0; i<pDim->GetSize();++i )
635 sal_Int32 lb = nBase;
636 SbiExprNode* pNode = pDim->Get(i)->GetExprNode();
637 sal_Int32 ub = pNode->GetNumber();
638 if ( !pDim->Get( i )->IsBased() ) // each dim is low/up
640 if ( ++i >= pDim->GetSize() ) // trouble
641 StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
642 pNode = pDim->Get(i)->GetExprNode();
643 lb = ub;
644 ub = pNode->GetNumber();
646 else if ( !bCompatible )
647 ub += nBase;
648 pArray->AddDim32( lb, ub );
650 pArray->setHasFixedSize( true );
652 else
653 pArray->unoAddDim( 0, -1 ); // variant array
654 SbxFlagBits nSavFlags = pTypeElem->GetFlags();
655 // need to reset the FIXED flag
656 // when calling PutObject ( because the type will not match Object )
657 pTypeElem->ResetFlag( SBX_FIXED );
658 pTypeElem->PutObject( pArray );
659 pTypeElem->SetFlags( nSavFlags );
661 // Nested user type?
662 if( eElemType == SbxOBJECT )
664 sal_uInt16 nElemTypeId = pElem->GetTypeId();
665 if( nElemTypeId != 0 )
667 OUString aTypeName( aGblStrings.Find( nElemTypeId ) );
668 SbxObject* pTypeObj = static_cast< SbxObject* >( rTypeArray->Find( aTypeName, SbxCLASS_OBJECT ) );
669 if( pTypeObj != NULL )
671 SbxObject* pCloneObj = cloneTypeObjectImpl( *pTypeObj );
672 pTypeElem->PutObject( pCloneObj );
676 pTypeMembers->Insert( pTypeElem, pTypeMembers->Count() );
678 delete pDim, pDim = NULL;
679 pElem.reset();
683 pType->Remove( OUString("Name"), SbxCLASS_DONTCARE );
684 pType->Remove( OUString("Parent"), SbxCLASS_DONTCARE );
686 rTypeArray->Insert (pType,rTypeArray->Count());
690 // Declaration of Enum type
692 void SbiParser::Enum()
694 DefEnum( false );
697 void SbiParser::DefEnum( bool bPrivate )
699 // Read a the new Token. It had to be a symbol
700 if (!TestSymbol())
701 return;
703 OUString aEnumName = aSym;
704 if( rEnumArray->Find(aEnumName,SbxCLASS_OBJECT) )
706 Error( SbERR_VAR_DEFINED, aSym );
707 return;
710 SbxObject *pEnum = new SbxObject( aEnumName );
711 if( bPrivate )
713 pEnum->SetFlag( SBX_PRIVATE );
715 SbiSymDef* pElem;
716 SbiDimList* pDim;
717 bool bDone = false;
719 // Starting with -1 to make first default value 0 after ++
720 sal_Int32 nCurrentEnumValue = -1;
721 while( !bDone && !IsEof() )
723 switch( Peek() )
725 case ENDENUM :
726 pElem = NULL;
727 bDone = true;
728 Next();
729 break;
731 case EOLN :
732 case REM :
733 pElem = NULL;
734 Next();
735 break;
737 default:
739 // TODO: Check existing!
740 pDim = NULL;
741 pElem = VarDecl( &pDim, false, true );
742 if( !pElem )
744 bDone = true; // Error occurred
745 break;
747 else if( pDim )
749 delete pDim;
750 Error( SbERR_SYNTAX );
751 bDone = true; // Error occurred
752 break;
755 SbiExpression aVar( this, *pElem );
756 if( Peek() == EQ )
758 Next();
760 SbiConstExpression aExpr( this );
761 if( aExpr.IsValid() )
763 SbxVariableRef xConvertVar = new SbxVariable();
764 if( aExpr.GetType() == SbxSTRING )
765 xConvertVar->PutString( aExpr.GetString() );
766 else
767 xConvertVar->PutDouble( aExpr.GetValue() );
769 nCurrentEnumValue = xConvertVar->GetLong();
772 else
773 nCurrentEnumValue++;
775 SbiSymPool* pPoolToUse = bPrivate ? pPool : &aGlobals;
777 SbiSymDef* pOld = pPoolToUse->Find( pElem->GetName() );
778 if( pOld )
780 Error( SbERR_VAR_DEFINED, pElem->GetName() );
781 bDone = true; // Error occurred
782 break;
785 pPool->Add( pElem );
787 if( !bPrivate )
789 SbiOpcode eOp = _GLOBAL;
790 aGen.BackChain( nGblChain );
791 nGblChain = 0;
792 bGblDefs = bNewGblDefs = true;
793 aGen.Gen(
794 eOp, pElem->GetId(),
795 sal::static_int_cast< sal_uInt16 >( pElem->GetType() ) );
797 aVar.Gen();
798 sal_uInt16 nStringId = aGen.GetParser()->aGblStrings.Add( nCurrentEnumValue, SbxLONG );
799 aGen.Gen( _NUMBER, nStringId );
800 aGen.Gen( _PUTC );
803 SbiConstDef* pConst = pElem->GetConstDef();
804 pConst->Set( nCurrentEnumValue, SbxLONG );
807 if( pElem )
809 SbxArray *pEnumMembers = pEnum->GetProperties();
810 SbxProperty *pEnumElem = new SbxProperty( pElem->GetName(), SbxLONG );
811 pEnumElem->PutLong( nCurrentEnumValue );
812 pEnumElem->ResetFlag( SBX_WRITE );
813 pEnumElem->SetFlag( SBX_CONST );
814 pEnumMembers->Insert( pEnumElem, pEnumMembers->Count() );
818 pEnum->Remove( OUString("Name"), SbxCLASS_DONTCARE );
819 pEnum->Remove( OUString("Parent"), SbxCLASS_DONTCARE );
821 rEnumArray->Insert( pEnum, rEnumArray->Count() );
825 // Procedure-Declaration
826 // the first Token is already read in (SUB/FUNCTION)
827 // xxx Name [LIB "name"[ALIAS "name"]][(Parameter)][AS TYPE]
829 SbiProcDef* SbiParser::ProcDecl( bool bDecl )
831 bool bFunc = ( eCurTok == FUNCTION );
832 bool bProp = ( eCurTok == GET || eCurTok == SET || eCurTok == LET );
833 if( !TestSymbol() ) return NULL;
834 OUString aName( aSym );
835 SbxDataType eType = eScanType;
836 SbiProcDef* pDef = new SbiProcDef( this, aName, true );
837 pDef->SetType( eType );
838 if( Peek() == _CDECL_ )
840 Next(); pDef->SetCdecl();
842 if( Peek() == LIB )
844 Next();
845 if( Next() == FIXSTRING )
847 pDef->GetLib() = aSym;
849 else
851 Error( SbERR_SYNTAX );
854 if( Peek() == ALIAS )
856 Next();
857 if( Next() == FIXSTRING )
859 pDef->GetAlias() = aSym;
861 else
863 Error( SbERR_SYNTAX );
866 if( !bDecl )
868 // CDECL, LIB and ALIAS are invalid
869 if( !pDef->GetLib().isEmpty() )
871 Error( SbERR_UNEXPECTED, LIB );
873 if( !pDef->GetAlias().isEmpty() )
875 Error( SbERR_UNEXPECTED, ALIAS );
877 if( pDef->IsCdecl() )
879 Error( SbERR_UNEXPECTED, _CDECL_ );
881 pDef->SetCdecl( false );
882 pDef->GetLib().clear();
883 pDef->GetAlias().clear();
885 else if( pDef->GetLib().isEmpty() )
887 // ALIAS and CDECL only together with LIB
888 if( !pDef->GetAlias().isEmpty() )
890 Error( SbERR_UNEXPECTED, ALIAS );
892 if( pDef->IsCdecl() )
894 Error( SbERR_UNEXPECTED, _CDECL_ );
896 pDef->SetCdecl( false );
897 pDef->GetAlias().clear();
899 // Brackets?
900 if( Peek() == LPAREN )
902 Next();
903 if( Peek() == RPAREN )
905 Next();
907 else
909 for(;;)
911 bool bByVal = false;
912 bool bOptional = false;
913 bool bParamArray = false;
914 while( Peek() == BYVAL || Peek() == BYREF || Peek() == _OPTIONAL_ )
916 if( Peek() == BYVAL )
918 bByVal = true;
920 else if ( Peek() == BYREF )
922 bByVal = false;
924 else if ( Peek() == _OPTIONAL_ )
926 bOptional = true;
928 Next();
930 if( bCompatible && Peek() == PARAMARRAY )
932 if( bByVal || bOptional )
934 Error( SbERR_UNEXPECTED, PARAMARRAY );
936 Next();
937 bParamArray = true;
939 SbiSymDef* pPar = VarDecl( NULL, false, false );
940 if( !pPar )
942 break;
944 if( bByVal )
946 pPar->SetByVal();
948 if( bOptional )
950 pPar->SetOptional();
952 if( bParamArray )
954 pPar->SetParamArray();
956 pDef->GetParams().Add( pPar );
957 SbiToken eTok = Next();
958 if( eTok != COMMA && eTok != RPAREN )
960 bool bError2 = true;
961 if( bOptional && bCompatible && eTok == EQ )
963 boost::scoped_ptr<SbiConstExpression> pDefaultExpr(new SbiConstExpression( this ));
964 SbxDataType eType2 = pDefaultExpr->GetType();
966 sal_uInt16 nStringId;
967 if( eType2 == SbxSTRING )
969 nStringId = aGblStrings.Add( pDefaultExpr->GetString() );
971 else
973 nStringId = aGblStrings.Add( pDefaultExpr->GetValue(), eType2 );
975 pPar->SetDefaultId( nStringId );
976 pDefaultExpr.reset();
978 eTok = Next();
979 if( eTok == COMMA || eTok == RPAREN )
981 bError2 = false;
984 if( bError2 )
986 Error( SbERR_EXPECTED, RPAREN );
987 break;
990 if( eTok == RPAREN )
992 break;
997 TypeDecl( *pDef );
998 if( eType != SbxVARIANT && pDef->GetType() != eType )
1000 Error( SbERR_BAD_DECLARATION, aName );
1002 if( pDef->GetType() == SbxVARIANT && !( bFunc || bProp ) )
1004 pDef->SetType( SbxEMPTY );
1006 return pDef;
1009 // DECLARE
1011 void SbiParser::Declare()
1013 DefDeclare( false );
1016 void SbiParser::DefDeclare( bool bPrivate )
1018 Next();
1019 if( eCurTok != SUB && eCurTok != FUNCTION )
1021 Error( SbERR_UNEXPECTED, eCurTok );
1023 else
1025 bool bFunction = (eCurTok == FUNCTION);
1027 SbiProcDef* pDef = ProcDecl( true );
1028 if( pDef )
1030 if( pDef->GetLib().isEmpty() )
1032 Error( SbERR_EXPECTED, LIB );
1034 // Is it already there?
1035 SbiSymDef* pOld = aPublics.Find( pDef->GetName() );
1036 if( pOld )
1038 SbiProcDef* p = pOld->GetProcDef();
1039 if( !p )
1041 // Declared as a variable
1042 Error( SbERR_BAD_DECLARATION, pDef->GetName() );
1043 delete pDef;
1044 pDef = NULL;
1046 else
1048 pDef->Match( p );
1051 else
1053 aPublics.Add( pDef );
1055 if ( pDef )
1057 pDef->SetPublic( !bPrivate );
1059 // New declare handling
1060 if( !pDef->GetLib().isEmpty())
1062 if( bNewGblDefs && nGblChain == 0 )
1064 nGblChain = aGen.Gen( _JUMP, 0 );
1065 bNewGblDefs = false;
1068 sal_uInt16 nSavLine = nLine;
1069 aGen.Statement();
1070 pDef->Define();
1071 pDef->SetLine1( nSavLine );
1072 pDef->SetLine2( nSavLine );
1074 SbiSymPool& rPool = pDef->GetParams();
1075 sal_uInt16 nParCount = rPool.GetSize();
1077 SbxDataType eType = pDef->GetType();
1078 if( bFunction )
1080 aGen.Gen( _PARAM, 0, sal::static_int_cast< sal_uInt16 >( eType ) );
1082 if( nParCount > 1 )
1084 aGen.Gen( _ARGC );
1086 for( sal_uInt16 i = 1 ; i < nParCount ; ++i )
1088 SbiSymDef* pParDef = rPool.Get( i );
1089 SbxDataType eParType = pParDef->GetType();
1091 aGen.Gen( _PARAM, i, sal::static_int_cast< sal_uInt16 >( eParType ) );
1092 aGen.Gen( _ARGV );
1094 sal_uInt16 nTyp = sal::static_int_cast< sal_uInt16 >( pParDef->GetType() );
1095 if( pParDef->IsByVal() )
1097 // Reset to avoid additional byval in call to wrapper function
1098 pParDef->SetByVal( false );
1099 nTyp |= 0x8000;
1101 aGen.Gen( _ARGTYP, nTyp );
1105 aGen.Gen( _LIB, aGblStrings.Add( pDef->GetLib() ) );
1107 SbiOpcode eOp = pDef->IsCdecl() ? _CALLC : _CALL;
1108 sal_uInt16 nId = pDef->GetId();
1109 if( !pDef->GetAlias().isEmpty() )
1111 nId = ( nId & 0x8000 ) | aGblStrings.Add( pDef->GetAlias() );
1113 if( nParCount > 1 )
1115 nId |= 0x8000;
1117 aGen.Gen( eOp, nId, sal::static_int_cast< sal_uInt16 >( eType ) );
1119 if( bFunction )
1121 aGen.Gen( _PUT );
1123 aGen.Gen( _LEAVE );
1130 void SbiParser::Attribute()
1132 // TODO: Need to implement the method as an attributed object.
1133 while( Next() != EQ )
1135 if( Next() != DOT)
1137 break;
1141 if( eCurTok != EQ )
1143 Error( SbERR_SYNTAX );
1145 else
1147 SbiExpression aValue( this );
1149 // Don't generate any code - just discard it.
1152 // Call of a SUB or a FUNCTION
1154 void SbiParser::Call()
1156 SbiExpression aVar( this, SbSYMBOL );
1157 aVar.Gen( FORCE_CALL );
1158 aGen.Gen( _GET );
1161 // SUB/FUNCTION
1163 void SbiParser::SubFunc()
1165 DefProc( false, false );
1168 // Read in of a procedure
1170 void SbiParser::DefProc( bool bStatic, bool bPrivate )
1172 sal_uInt16 l1 = nLine;
1173 bool bSub = ( eCurTok == SUB );
1174 bool bProperty = ( eCurTok == PROPERTY );
1175 PropertyMode ePropertyMode = PROPERTY_MODE_NONE;
1176 if( bProperty )
1178 Next();
1179 if( eCurTok == GET )
1181 ePropertyMode = PROPERTY_MODE_GET;
1183 else if( eCurTok == LET )
1185 ePropertyMode = PROPERTY_MODE_LET;
1187 else if( eCurTok == SET )
1189 ePropertyMode = PROPERTY_MODE_SET;
1191 else
1193 Error( SbERR_EXPECTED, "Get or Let or Set" );
1197 SbiToken eExit = eCurTok;
1198 SbiProcDef* pDef = ProcDecl( false );
1199 if( !pDef )
1201 return;
1203 pDef->setPropertyMode( ePropertyMode );
1205 // Is the Proc already declared?
1206 SbiSymDef* pOld = aPublics.Find( pDef->GetName() );
1207 if( pOld )
1209 bool bError_ = false;
1211 pProc = pOld->GetProcDef();
1212 if( !pProc )
1214 // Declared as a variable
1215 Error( SbERR_BAD_DECLARATION, pDef->GetName() );
1216 delete pDef;
1217 pProc = NULL;
1218 bError_ = true;
1220 // #100027: Multiple declaration -> Error
1221 // #112787: Not for setup, REMOVE for 8
1222 else if( pProc->IsUsedForProcDecl() )
1224 PropertyMode ePropMode = pDef->getPropertyMode();
1225 if( ePropMode == PROPERTY_MODE_NONE || ePropMode == pProc->getPropertyMode() )
1227 Error( SbERR_PROC_DEFINED, pDef->GetName() );
1228 delete pDef;
1229 pProc = NULL;
1230 bError_ = true;
1234 if( !bError_ )
1236 pDef->Match( pProc );
1237 pProc = pDef;
1240 else
1242 aPublics.Add( pDef ), pProc = pDef;
1244 if( !pProc )
1246 return;
1248 pProc->SetPublic( !bPrivate );
1250 // Now we set the search hierarchy for symbols as well as the
1251 // current procedure.
1252 aPublics.SetProcId( pProc->GetId() );
1253 pProc->GetParams().SetParent( &aPublics );
1254 if( bStatic )
1256 if ( bVBASupportOn )
1258 pProc->SetStatic( true );
1260 else
1262 Error( SbERR_NOT_IMPLEMENTED ); // STATIC SUB ...
1265 else
1267 pProc->SetStatic( false );
1269 // Normal case: Local variable->parameter->global variable
1270 pProc->GetLocals().SetParent( &pProc->GetParams() );
1271 pPool = &pProc->GetLocals();
1273 pProc->Define();
1274 OpenBlock( eExit );
1275 StmntBlock( bSub ? ENDSUB : (bProperty ? ENDPROPERTY : ENDFUNC) );
1276 sal_uInt16 l2 = nLine;
1277 pProc->SetLine1( l1 );
1278 pProc->SetLine2( l2 );
1279 pPool = &aPublics;
1280 aPublics.SetProcId( 0 );
1281 // Open labels?
1282 pProc->GetLabels().CheckRefs();
1283 CloseBlock();
1284 aGen.Gen( _LEAVE );
1285 pProc = NULL;
1288 // STATIC variable|procedure
1290 void SbiParser::Static()
1292 DefStatic( false );
1295 void SbiParser::DefStatic( bool bPrivate )
1297 SbiSymPool* p;
1299 switch( Peek() )
1301 case SUB:
1302 case FUNCTION:
1303 case PROPERTY:
1304 // End global chain if necessary (not done in
1305 // SbiParser::Parse() under these conditions
1306 if( bNewGblDefs && nGblChain == 0 )
1308 nGblChain = aGen.Gen( _JUMP, 0 );
1309 bNewGblDefs = false;
1311 Next();
1312 DefProc( true, bPrivate );
1313 break;
1314 default:
1315 if( !pProc )
1317 Error( SbERR_NOT_IN_SUBR );
1319 // Reset the Pool, so that STATIC-Declarations go into the
1320 // global Pool
1321 p = pPool;
1322 pPool = &aPublics;
1323 DefVar( _STATIC, true );
1324 pPool = p;
1325 break;
1329 bool SbiParser::IsUnoInterface(const OUString& sTypeName)
1333 return css::reflection::theCoreReflection::get(
1334 comphelper::getProcessComponentContext())->forName(sTypeName).is();
1336 catch(const Exception&)
1338 OSL_FAIL("Could not create reflection.CoreReflection.");
1340 return false;
1343 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */