1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_basic.hxx"
26 #include <basic/sbx.hxx>
27 #include "sbcomp.hxx"
28
29 SbxObject* cloneTypeObjectImpl( const SbxObject& rTypeObj );
30
31 // Deklaration einer Variablen
32 // Bei Fehlern wird bis zum Komma oder Newline geparst.
33 // Returnwert: eine neue Instanz, die eingefuegt und dann geloescht wird.
34 // Array-Indexe werden als SbiDimList zurueckgegeben
35
VarDecl(SbiDimList ** ppDim,sal_Bool bStatic,sal_Bool bConst)36 SbiSymDef* SbiParser::VarDecl( SbiDimList** ppDim, sal_Bool bStatic, sal_Bool bConst )
37 {
38 bool bWithEvents = false;
39 if( Peek() == WITHEVENTS )
40 {
41 Next();
42 bWithEvents = true;
43 }
44 if( !TestSymbol() ) return NULL;
45 SbxDataType t = eScanType;
46 SbiSymDef* pDef = bConst ? new SbiConstDef( aSym ) : new SbiSymDef( aSym );
47 SbiDimList* pDim = NULL;
48 // Klammern?
49 if( Peek() == LPAREN )
50 {
51 pDim = new SbiDimList( this );
52 if( !pDim->GetDims() )
53 pDef->SetWithBrackets();
54 }
55 pDef->SetType( t );
56 if( bStatic )
57 pDef->SetStatic();
58 if( bWithEvents )
59 pDef->SetWithEvents();
60 TypeDecl( *pDef );
61 if( !ppDim && pDim )
62 {
63 if(pDim->GetDims() )
64 Error( SbERR_EXPECTED, "()" );
65 delete pDim;
66 }
67 else if( ppDim )
68 *ppDim = pDim;
69 return pDef;
70 }
71
72 // Aufloesen einer AS-Typdeklaration
73 // Der Datentyp wird in die uebergebene Variable eingetragen
74
TypeDecl(SbiSymDef & rDef,sal_Bool bAsNewAlreadyParsed)75 void SbiParser::TypeDecl( SbiSymDef& rDef, sal_Bool bAsNewAlreadyParsed )
76 {
77 SbxDataType eType = rDef.GetType();
78 short nSize = 0;
79 if( bAsNewAlreadyParsed || Peek() == AS )
80 {
81 if( !bAsNewAlreadyParsed )
82 Next();
83 rDef.SetDefinedAs();
84 String aType;
85 SbiToken eTok = Next();
86 if( !bAsNewAlreadyParsed && eTok == NEW )
87 {
88 rDef.SetNew();
89 eTok = Next();
90 }
91 switch( eTok )
92 {
93 case ANY:
94 if( rDef.IsNew() )
95 Error( SbERR_SYNTAX );
96 eType = SbxVARIANT; break;
97 case TINTEGER:
98 case TLONG:
99 case TSINGLE:
100 case TDOUBLE:
101 case TCURRENCY:
102 case TDATE:
103 case TSTRING:
104 case TOBJECT:
105 case _ERROR_:
106 case TBOOLEAN:
107 case TVARIANT:
108 case TBYTE:
109 if( rDef.IsNew() )
110 Error( SbERR_SYNTAX );
111 eType = (eTok==TBYTE) ? SbxBYTE : SbxDataType( eTok - TINTEGER + SbxINTEGER );
112 if( eType == SbxSTRING )
113 {
114 // STRING*n ?
115 if( Peek() == MUL )
116 { // fixed size!
117 Next();
118 SbiConstExpression aSize( this );
119 nSize = aSize.GetShortValue();
120 if( nSize < 0 || (bVBASupportOn && nSize <= 0) )
121 Error( SbERR_OUT_OF_RANGE );
122 else
123 rDef.SetFixedStringLength( nSize );
124 }
125 }
126 break;
127 case SYMBOL: // kann nur ein TYPE oder eine Objektklasse sein!
128 if( eScanType != SbxVARIANT )
129 Error( SbERR_SYNTAX );
130 else
131 {
132 String aCompleteName = aSym;
133
134 // #52709 DIM AS NEW fuer Uno mit voll-qualifizierten Namen
135 if( Peek() == DOT )
136 {
137 String aDotStr( '.' );
138 while( Peek() == DOT )
139 {
140 aCompleteName += aDotStr;
141 Next();
142 SbiToken ePeekTok = Peek();
143 if( ePeekTok == SYMBOL || IsKwd( ePeekTok ) )
144 {
145 Next();
146 aCompleteName += aSym;
147 }
148 else
149 {
150 Next();
151 Error( SbERR_UNEXPECTED, SYMBOL );
152 break;
153 }
154 }
155 }
156 else if( rEnumArray->Find( aCompleteName, SbxCLASS_OBJECT ) )
157 {
158 eType = SbxLONG;
159 break;
160 }
161
162 // In den String-Pool uebernehmen
163 rDef.SetTypeId( aGblStrings.Add( aCompleteName ) );
164
165 if( rDef.IsNew() && pProc == NULL )
166 aRequiredTypes.push_back( aCompleteName );
167 }
168 eType = SbxOBJECT;
169 break;
170 case FIXSTRING: // new syntax for complex UNO types
171 rDef.SetTypeId( aGblStrings.Add( aSym ) );
172 eType = SbxOBJECT;
173 break;
174 default:
175 Error( SbERR_UNEXPECTED, eTok );
176 Next();
177 }
178 // Die Variable koennte mit Suffix deklariert sein
179 if( rDef.GetType() != SbxVARIANT )
180 {
181 if( rDef.GetType() != eType )
182 Error( SbERR_VAR_DEFINED, rDef.GetName() );
183 else if( eType == SbxSTRING && rDef.GetLen() != nSize )
184 Error( SbERR_VAR_DEFINED, rDef.GetName() );
185 }
186 rDef.SetType( eType );
187 rDef.SetLen( nSize );
188 }
189 }
190
191 // Hier werden Variable, Arrays und Strukturen definiert.
192 // DIM/PRIVATE/PUBLIC/GLOBAL
193
Dim()194 void SbiParser::Dim()
195 {
196 DefVar( _DIM, ( pProc && bVBASupportOn ) ? pProc->IsStatic() : sal_False );
197 }
198
DefVar(SbiOpcode eOp,sal_Bool bStatic)199 void SbiParser::DefVar( SbiOpcode eOp, sal_Bool bStatic )
200 {
201 SbiSymPool* pOldPool = pPool;
202 sal_Bool bSwitchPool = sal_False;
203 sal_Bool bPersistantGlobal = sal_False;
204 SbiToken eFirstTok = eCurTok;
205 if( pProc && ( eCurTok == GLOBAL || eCurTok == PUBLIC || eCurTok == PRIVATE ) )
206 Error( SbERR_NOT_IN_SUBR, eCurTok );
207 if( eCurTok == PUBLIC || eCurTok == GLOBAL )
208 {
209 bSwitchPool = sal_True; // im richtigen Moment auf globalen Pool schalten
210 if( eCurTok == GLOBAL )
211 bPersistantGlobal = sal_True;
212 }
213 // behavior in VBA is that a module scope variable's lifetime is
214 // tied to the document. e.g. a module scope variable is global
215 if( GetBasic()->IsDocBasic() && bVBASupportOn && !pProc )
216 bPersistantGlobal = sal_True;
217 // PRIVATE ist Synonym fuer DIM
218 // _CONST_?
219 sal_Bool bConst = sal_False;
220 if( eCurTok == _CONST_ )
221 bConst = sal_True;
222 else if( Peek() == _CONST_ )
223 Next(), bConst = sal_True;
224
225 // #110004 It can also be a sub/function
226 if( !bConst && (eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY ||
227 eCurTok == STATIC || eCurTok == ENUM || eCurTok == DECLARE || eCurTok == TYPE) )
228 {
229 // Next token is read here, because !bConst
230 bool bPrivate = ( eFirstTok == PRIVATE );
231
232 if( eCurTok == STATIC )
233 {
234 Next();
235 DefStatic( bPrivate );
236 }
237 else if( eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY )
238 {
239 // End global chain if necessary (not done in
240 // SbiParser::Parse() under these conditions
241 if( bNewGblDefs && nGblChain == 0 )
242 {
243 nGblChain = aGen.Gen( _JUMP, 0 );
244 bNewGblDefs = sal_False;
245 }
246 Next();
247 DefProc( sal_False, bPrivate );
248 return;
249 }
250 else if( eCurTok == ENUM )
251 {
252 Next();
253 DefEnum( bPrivate );
254 return;
255 }
256 else if( eCurTok == DECLARE )
257 {
258 Next();
259 DefDeclare( bPrivate );
260 return;
261 }
262 // #i109049
263 else if( eCurTok == TYPE )
264 {
265 Next();
266 DefType( bPrivate );
267 return;
268 }
269 }
270
271 #ifdef SHARED
272 #define tmpSHARED
273 #undef SHARED
274 #endif
275 // SHARED wird ignoriert
276 if( Peek() == SHARED ) Next();
277 #ifdef tmpSHARED
278 #define SHARED
279 #undef tmpSHARED
280 #endif
281 // PRESERVE nur bei REDIM
282 if( Peek() == PRESERVE )
283 {
284 Next();
285 if( eOp == _REDIM )
286 eOp = _REDIMP;
287 else
288 Error( SbERR_UNEXPECTED, eCurTok );
289 }
290 SbiSymDef* pDef;
291 SbiDimList* pDim;
292
293 // AB 9.7.97, #40689, Statics -> Modul-Initialisierung, in Sub ueberspringen
294 sal_uInt32 nEndOfStaticLbl = 0;
295 if( !bVBASupportOn && bStatic )
296 {
297 nEndOfStaticLbl = aGen.Gen( _JUMP, 0 );
298 aGen.Statement(); // bei static hier nachholen
299 }
300
301 sal_Bool bDefined = sal_False;
302 while( ( pDef = VarDecl( &pDim, bStatic, bConst ) ) != NULL )
303 {
304 EnableErrors();
305 // Variable suchen:
306 if( bSwitchPool )
307 pPool = &aGlobals;
308 SbiSymDef* pOld = pPool->Find( pDef->GetName() );
309 // AB 31.3.1996, #25651#, auch in Runtime-Library suchen
310 sal_Bool bRtlSym = sal_False;
311 if( !pOld )
312 {
313 pOld = CheckRTLForSym( pDef->GetName(), SbxVARIANT );
314 if( pOld )
315 bRtlSym = sal_True;
316 }
317 if( pOld && !(eOp == _REDIM || eOp == _REDIMP) )
318 {
319 if( pDef->GetScope() == SbLOCAL && pOld->GetScope() != SbLOCAL )
320 pOld = NULL;
321 }
322 if( pOld )
323 {
324 bDefined = sal_True;
325 // Bei RTL-Symbol immer Fehler
326 if( !bRtlSym && (eOp == _REDIM || eOp == _REDIMP) )
327 {
328 // Bei REDIM die Attribute vergleichen
329 SbxDataType eDefType;
330 bool bError_ = false;
331 if( pOld->IsStatic() )
332 {
333 bError_ = true;
334 }
335 else if( pOld->GetType() != ( eDefType = pDef->GetType() ) )
336 {
337 if( !( eDefType == SbxVARIANT && !pDef->IsDefinedAs() ) )
338 bError_ = true;
339 }
340 if( bError_ )
341 Error( SbERR_VAR_DEFINED, pDef->GetName() );
342 }
343 else
344 Error( SbERR_VAR_DEFINED, pDef->GetName() );
345 delete pDef; pDef = pOld;
346 }
347 else
348 pPool->Add( pDef );
349
350 // #36374: Variable vor Unterscheidung IsNew() anlegen
351 // Sonst Error bei Dim Identifier As New Type und option explicit
352 if( !bDefined && !(eOp == _REDIM || eOp == _REDIMP)
353 && ( !bConst || pDef->GetScope() == SbGLOBAL ) )
354 {
355 // Variable oder globale Konstante deklarieren
356 SbiOpcode eOp2;
357 switch ( pDef->GetScope() )
358 {
359 case SbGLOBAL: eOp2 = bPersistantGlobal ? _GLOBAL_P : _GLOBAL;
360 goto global;
361 case SbPUBLIC: eOp2 = bPersistantGlobal ? _PUBLIC_P : _PUBLIC;
362 // AB 9.7.97, #40689, kein eigener Opcode mehr
363 if( bVBASupportOn && bStatic )
364 {
365 eOp2 = _STATIC;
366 break;
367 }
368 global: aGen.BackChain( nGblChain );
369 nGblChain = 0;
370 bGblDefs = bNewGblDefs = sal_True;
371 break;
372 default: eOp2 = _LOCAL;
373 }
374 sal_uInt32 nOpnd2 = sal::static_int_cast< sal_uInt16 >( pDef->GetType() );
375 if( pDef->IsWithEvents() )
376 nOpnd2 |= SBX_TYPE_WITH_EVENTS_FLAG;
377
378 if( bCompatible && pDef->IsNew() )
379 nOpnd2 |= SBX_TYPE_DIM_AS_NEW_FLAG;
380
381 short nFixedStringLength = pDef->GetFixedStringLength();
382 if( nFixedStringLength >= 0 )
383 nOpnd2 |= (SBX_FIXED_LEN_STRING_FLAG + (sal_uInt32(nFixedStringLength) << 17)); // len = all bits above 0x10000
384
385 if( pDim != NULL && pDim->GetDims() > 0 )
386 nOpnd2 |= SBX_TYPE_VAR_TO_DIM_FLAG;
387
388 aGen.Gen( eOp2, pDef->GetId(), nOpnd2 );
389 }
390
391 // Initialisierung fuer selbstdefinierte Datentypen
392 // und per NEW angelegte Variable
393 if( pDef->GetType() == SbxOBJECT
394 && pDef->GetTypeId() )
395 {
396 if( !bCompatible && !pDef->IsNew() )
397 {
398 String aTypeName( aGblStrings.Find( pDef->GetTypeId() ) );
399 if( rTypeArray->Find( aTypeName, SbxCLASS_OBJECT ) == NULL )
400 Error( SbERR_UNDEF_TYPE, aTypeName );
401 }
402
403 if( bConst )
404 {
405 Error( SbERR_SYNTAX );
406 }
407
408 if( pDim )
409 {
410 if( eOp == _REDIMP )
411 {
412 SbiExpression aExpr( this, *pDef, NULL );
413 aExpr.Gen();
414 aGen.Gen( _REDIMP_ERASE );
415
416 pDef->SetDims( pDim->GetDims() );
417 SbiExpression aExpr2( this, *pDef, pDim );
418 aExpr2.Gen();
419 aGen.Gen( _DCREATE_REDIMP, pDef->GetId(), pDef->GetTypeId() );
420 }
421 else
422 {
423 pDef->SetDims( pDim->GetDims() );
424 SbiExpression aExpr( this, *pDef, pDim );
425 aExpr.Gen();
426 aGen.Gen( _DCREATE, pDef->GetId(), pDef->GetTypeId() );
427 }
428 }
429 else
430 {
431 SbiExpression aExpr( this, *pDef );
432 aExpr.Gen();
433 SbiOpcode eOp_ = pDef->IsNew() ? _CREATE : _TCREATE;
434 aGen.Gen( eOp_, pDef->GetId(), pDef->GetTypeId() );
435 aGen.Gen( _SET );
436 }
437 }
438 else
439 {
440 if( bConst )
441 {
442 // Konstanten-Definition
443 if( pDim )
444 {
445 Error( SbERR_SYNTAX );
446 delete pDim;
447 }
448 SbiExpression aVar( this, *pDef );
449 if( !TestToken( EQ ) )
450 goto MyBreak; // AB 24.6.1996 (s.u.)
451 SbiConstExpression aExpr( this );
452 if( !bDefined && aExpr.IsValid() )
453 {
454 if( pDef->GetScope() == SbGLOBAL )
455 {
456 // Nur Code fuer globale Konstante erzeugen!
457 aVar.Gen();
458 aExpr.Gen();
459 aGen.Gen( _PUTC );
460 }
461 SbiConstDef* pConst = pDef->GetConstDef();
462 if( aExpr.GetType() == SbxSTRING )
463 pConst->Set( aExpr.GetString() );
464 else
465 pConst->Set( aExpr.GetValue(), aExpr.GetType() );
466 }
467 }
468 else if( pDim )
469 {
470 // Die Variable dimensionieren
471 // Bei REDIM die Var vorher loeschen
472 if( eOp == _REDIM )
473 {
474 SbiExpression aExpr( this, *pDef, NULL );
475 aExpr.Gen();
476 if ( bVBASupportOn )
477 // delete the array but
478 // clear the variable ( this
479 // allows the processing of
480 // the param to happen as normal without errors ( ordinary ERASE just clears the array )
481 aGen.Gen( _ERASE_CLEAR );
482 else
483 aGen.Gen( _ERASE );
484 }
485 else if( eOp == _REDIMP )
486 {
487 SbiExpression aExpr( this, *pDef, NULL );
488 aExpr.Gen();
489 aGen.Gen( _REDIMP_ERASE );
490 }
491 pDef->SetDims( pDim->GetDims() );
492 if( bPersistantGlobal )
493 pDef->SetGlobal( sal_True );
494 SbiExpression aExpr( this, *pDef, pDim );
495 aExpr.Gen();
496 pDef->SetGlobal( sal_False );
497 aGen.Gen( (eOp == _STATIC) ? _DIM : eOp );
498 }
499 }
500 if( !TestComma() )
501 goto MyBreak; // AB 24.6.1996 (s.u.)
502
503 // #27963# AB, 24.6.1996
504 // Einfuehrung bSwitchPool (s.o.): pPool darf beim VarDecl-Aufruf
505 // noch nicht auf &aGlobals gesetzt sein.
506 // Ansonsten soll das Verhalten aber absolut identisch bleiben,
507 // d.h. pPool muss immer am Schleifen-Ende zurueckgesetzt werden.
508 // auch bei break
509 pPool = pOldPool;
510 continue; // MyBreak �berspingen
511 MyBreak:
512 pPool = pOldPool;
513 break;
514 }
515
516 // AB 9.7.97, #40689, Sprung ueber Statics-Deklaration abschliessen
517 if( !bVBASupportOn && bStatic )
518 {
519 // globalen Chain pflegen
520 nGblChain = aGen.Gen( _JUMP, 0 );
521 bGblDefs = bNewGblDefs = sal_True;
522
523 // fuer Sub Sprung auf Ende der statics eintragen
524 aGen.BackChain( nEndOfStaticLbl );
525 }
526
527 //pPool = pOldPool;
528 }
529
530 // Hier werden Arrays redimensioniert.
531
ReDim()532 void SbiParser::ReDim()
533 {
534 DefVar( _REDIM, ( pProc && bVBASupportOn ) ? pProc->IsStatic() : sal_False );
535 }
536
537 // ERASE array, ...
538
Erase()539 void SbiParser::Erase()
540 {
541 while( !bAbort )
542 {
543 SbiExpression aExpr( this, SbLVALUE );
544 aExpr.Gen();
545 aGen.Gen( _ERASE );
546 if( !TestComma() ) break;
547 }
548 }
549
550 // Deklaration eines Datentyps
551
Type()552 void SbiParser::Type()
553 {
554 DefType( sal_False );
555 }
556
DefType(sal_Bool bPrivate)557 void SbiParser::DefType( sal_Bool bPrivate )
558 {
559 // TODO: Use bPrivate
560 (void)bPrivate;
561
562 // Neues Token lesen, es muss ein Symbol sein
563 if (!TestSymbol())
564 return;
565
566 if (rTypeArray->Find(aSym,SbxCLASS_OBJECT))
567 {
568 Error( SbERR_VAR_DEFINED, aSym );
569 return;
570 }
571
572 SbxObject *pType = new SbxObject(aSym);
573
574 SbiSymDef* pElem;
575 SbiDimList* pDim = NULL;
576 sal_Bool bDone = sal_False;
577
578 while( !bDone && !IsEof() )
579 {
580 switch( Peek() )
581 {
582 case ENDTYPE :
583 pElem = NULL;
584 bDone = sal_True;
585 Next();
586 break;
587
588 case EOLN :
589 case REM :
590 pElem = NULL;
591 Next();
592 break;
593
594 default:
595 pDim = NULL;
596 pElem = VarDecl(&pDim,sal_False,sal_False);
597 if( !pElem )
598 bDone = sal_True; // Error occurred
599 }
600 if( pElem )
601 {
602 SbxArray *pTypeMembers = pType->GetProperties();
603 String aElemName = pElem->GetName();
604 if( pTypeMembers->Find( aElemName, SbxCLASS_DONTCARE) )
605 Error (SbERR_VAR_DEFINED);
606 else
607 {
608 SbxDataType eElemType = pElem->GetType();
609 SbxProperty *pTypeElem = new SbxProperty( aElemName, eElemType );
610 if( pDim )
611 {
612 SbxDimArray* pArray = new SbxDimArray( pElem->GetType() );
613 if ( pDim->GetSize() )
614 {
615 // Dimension the target array
616
617 for ( short i=0; i<pDim->GetSize();++i )
618 {
619 sal_Int32 ub = -1;
620 sal_Int32 lb = nBase;
621 SbiExprNode* pNode = pDim->Get(i)->GetExprNode();
622 ub = pNode->GetNumber();
623 if ( !pDim->Get( i )->IsBased() ) // each dim is low/up
624 {
625 if ( ++i >= pDim->GetSize() ) // trouble
626 StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
627 pNode = pDim->Get(i)->GetExprNode();
628 lb = ub;
629 ub = pNode->GetNumber();
630 }
631 else if ( !bCompatible )
632 ub += nBase;
633 pArray->AddDim32( lb, ub );
634 }
635 pArray->setHasFixedSize( true );
636 }
637 else
638 pArray->unoAddDim( 0, -1 ); // variant array
639 sal_uInt16 nSavFlags = pTypeElem->GetFlags();
640 // need to reset the FIXED flag
641 // when calling PutObject ( because the type will not match Object )
642 pTypeElem->ResetFlag( SBX_FIXED );
643 pTypeElem->PutObject( pArray );
644 pTypeElem->SetFlags( nSavFlags );
645 }
646 // Nested user type?
647 if( eElemType == SbxOBJECT )
648 {
649 sal_uInt16 nElemTypeId = pElem->GetTypeId();
650 if( nElemTypeId != 0 )
651 {
652 String aTypeName( aGblStrings.Find( nElemTypeId ) );
653 SbxObject* pTypeObj = static_cast< SbxObject* >( rTypeArray->Find( aTypeName, SbxCLASS_OBJECT ) );
654 if( pTypeObj != NULL )
655 {
656 SbxObject* pCloneObj = cloneTypeObjectImpl( *pTypeObj );
657 pTypeElem->PutObject( pCloneObj );
658 }
659 }
660 }
661 delete pDim;
662 pTypeMembers->Insert( pTypeElem, pTypeMembers->Count() );
663 }
664 delete pElem;
665 }
666 }
667
668 pType->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_DONTCARE );
669 pType->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Parent") ), SbxCLASS_DONTCARE );
670
671 rTypeArray->Insert (pType,rTypeArray->Count());
672 }
673
674
675 // Declaration of Enum type
676
Enum()677 void SbiParser::Enum()
678 {
679 DefEnum( sal_False );
680 }
681
DefEnum(sal_Bool bPrivate)682 void SbiParser::DefEnum( sal_Bool bPrivate )
683 {
684 // Neues Token lesen, es muss ein Symbol sein
685 if (!TestSymbol())
686 return;
687
688 String aEnumName = aSym;
689 if( rEnumArray->Find(aEnumName,SbxCLASS_OBJECT) )
690 {
691 Error( SbERR_VAR_DEFINED, aSym );
692 return;
693 }
694
695 SbxObject *pEnum = new SbxObject( aEnumName );
696 if( bPrivate )
697 pEnum->SetFlag( SBX_PRIVATE );
698
699 SbiSymDef* pElem;
700 SbiDimList* pDim;
701 sal_Bool bDone = sal_False;
702
703 // Starting with -1 to make first default value 0 after ++
704 sal_Int32 nCurrentEnumValue = -1;
705 while( !bDone && !IsEof() )
706 {
707 switch( Peek() )
708 {
709 case ENDENUM :
710 pElem = NULL;
711 bDone = sal_True;
712 Next();
713 break;
714
715 case EOLN :
716 case REM :
717 pElem = NULL;
718 Next();
719 break;
720
721 default:
722 {
723 // TODO: Check existing!
724 sal_Bool bDefined = sal_False;
725
726 pDim = NULL;
727 pElem = VarDecl( &pDim, sal_False, sal_True );
728 if( !pElem )
729 {
730 bDone = sal_True; // Error occurred
731 break;
732 }
733 else if( pDim )
734 {
735 delete pDim;
736 Error( SbERR_SYNTAX );
737 bDone = sal_True; // Error occurred
738 break;
739 }
740
741 SbiExpression aVar( this, *pElem );
742 if( Peek() == EQ )
743 {
744 Next();
745
746 SbiConstExpression aExpr( this );
747 if( !bDefined && aExpr.IsValid() )
748 {
749 SbxVariableRef xConvertVar = new SbxVariable();
750 if( aExpr.GetType() == SbxSTRING )
751 xConvertVar->PutString( aExpr.GetString() );
752 else
753 xConvertVar->PutDouble( aExpr.GetValue() );
754
755 nCurrentEnumValue = xConvertVar->GetLong();
756 }
757 }
758 else
759 nCurrentEnumValue++;
760
761 SbiSymPool* pPoolToUse = bPrivate ? pPool : &aGlobals;
762
763 SbiSymDef* pOld = pPoolToUse->Find( pElem->GetName() );
764 if( pOld )
765 {
766 Error( SbERR_VAR_DEFINED, pElem->GetName() );
767 bDone = sal_True; // Error occurred
768 break;
769 }
770
771 pPool->Add( pElem );
772
773 if( !bPrivate )
774 {
775 SbiOpcode eOp = _GLOBAL;
776 aGen.BackChain( nGblChain );
777 nGblChain = 0;
778 bGblDefs = bNewGblDefs = sal_True;
779 aGen.Gen(
780 eOp, pElem->GetId(),
781 sal::static_int_cast< sal_uInt16 >( pElem->GetType() ) );
782
783 aVar.Gen();
784 sal_uInt16 nStringId = aGen.GetParser()->aGblStrings.Add( nCurrentEnumValue, SbxLONG );
785 aGen.Gen( _NUMBER, nStringId );
786 aGen.Gen( _PUTC );
787 }
788
789 SbiConstDef* pConst = pElem->GetConstDef();
790 pConst->Set( nCurrentEnumValue, SbxLONG );
791 }
792 }
793 if( pElem )
794 {
795 SbxArray *pEnumMembers = pEnum->GetProperties();
796 SbxProperty *pEnumElem = new SbxProperty( pElem->GetName(), SbxLONG );
797 pEnumElem->PutLong( nCurrentEnumValue );
798 pEnumElem->ResetFlag( SBX_WRITE );
799 pEnumElem->SetFlag( SBX_CONST );
800 pEnumMembers->Insert( pEnumElem, pEnumMembers->Count() );
801 }
802 }
803
804 pEnum->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_DONTCARE );
805 pEnum->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Parent") ), SbxCLASS_DONTCARE );
806
807 rEnumArray->Insert( pEnum, rEnumArray->Count() );
808 }
809
810
811 // Prozedur-Deklaration
812 // das erste Token ist bereits eingelesen (SUB/FUNCTION)
813 // xxx Name [LIB "name"[ALIAS "name"]][(Parameter)][AS TYPE]
814
ProcDecl(sal_Bool bDecl)815 SbiProcDef* SbiParser::ProcDecl( sal_Bool bDecl )
816 {
817 sal_Bool bFunc = sal_Bool( eCurTok == FUNCTION );
818 sal_Bool bProp = sal_Bool( eCurTok == GET || eCurTok == SET || eCurTok == LET );
819 if( !TestSymbol() ) return NULL;
820 String aName( aSym );
821 SbxDataType eType = eScanType;
822 SbiProcDef* pDef = new SbiProcDef( this, aName, true );
823 pDef->SetType( eType );
824 if( Peek() == _CDECL_ )
825 {
826 Next(); pDef->SetCdecl();
827 }
828 if( Peek() == LIB )
829 {
830 Next();
831 if( Next() == FIXSTRING )
832 pDef->GetLib() = aSym;
833 else
834 Error( SbERR_SYNTAX );
835 }
836 if( Peek() == ALIAS )
837 {
838 Next();
839 if( Next() == FIXSTRING )
840 pDef->GetAlias() = aSym;
841 else
842 Error( SbERR_SYNTAX );
843 }
844 if( !bDecl )
845 {
846 // CDECL, LIB und ALIAS sind unzulaessig
847 if( pDef->GetLib().Len() )
848 Error( SbERR_UNEXPECTED, LIB );
849 if( pDef->GetAlias().Len() )
850 Error( SbERR_UNEXPECTED, ALIAS );
851 if( pDef->IsCdecl() )
852 Error( SbERR_UNEXPECTED, _CDECL_ );
853 pDef->SetCdecl( sal_False );
854 pDef->GetLib().Erase();
855 pDef->GetAlias().Erase();
856 }
857 else if( !pDef->GetLib().Len() )
858 {
859 // ALIAS und CDECL nur zusammen mit LIB
860 if( pDef->GetAlias().Len() )
861 Error( SbERR_UNEXPECTED, ALIAS );
862 if( pDef->IsCdecl() )
863 Error( SbERR_UNEXPECTED, _CDECL_ );
864 pDef->SetCdecl( sal_False );
865 pDef->GetAlias().Erase();
866 }
867 // Klammern?
868 if( Peek() == LPAREN )
869 {
870 Next();
871 if( Peek() == RPAREN )
872 Next();
873 else
874 for(;;) {
875 sal_Bool bByVal = sal_False;
876 sal_Bool bOptional = sal_False;
877 sal_Bool bParamArray = sal_False;
878 while( Peek() == BYVAL || Peek() == BYREF || Peek() == _OPTIONAL_ )
879 {
880 if ( Peek() == BYVAL ) Next(), bByVal = sal_True;
881 else if ( Peek() == BYREF ) Next(), bByVal = sal_False;
882 else if ( Peek() == _OPTIONAL_ ) Next(), bOptional = sal_True;
883 }
884 if( bCompatible && Peek() == PARAMARRAY )
885 {
886 if( bByVal || bOptional )
887 Error( SbERR_UNEXPECTED, PARAMARRAY );
888 Next();
889 bParamArray = sal_True;
890 }
891 SbiSymDef* pPar = VarDecl( NULL, sal_False, sal_False );
892 if( !pPar )
893 break;
894 if( bByVal )
895 pPar->SetByVal();
896 if( bOptional )
897 pPar->SetOptional();
898 if( bParamArray )
899 pPar->SetParamArray();
900 pDef->GetParams().Add( pPar );
901 SbiToken eTok = Next();
902 if( eTok != COMMA && eTok != RPAREN )
903 {
904 sal_Bool bError2 = sal_True;
905 if( bOptional && bCompatible && eTok == EQ )
906 {
907 SbiConstExpression* pDefaultExpr = new SbiConstExpression( this );
908 SbxDataType eType2 = pDefaultExpr->GetType();
909
910 sal_uInt16 nStringId;
911 if( eType2 == SbxSTRING )
912 nStringId = aGblStrings.Add( pDefaultExpr->GetString() );
913 else
914 nStringId = aGblStrings.Add( pDefaultExpr->GetValue(), eType2 );
915
916 pPar->SetDefaultId( nStringId );
917 delete pDefaultExpr;
918
919 eTok = Next();
920 if( eTok == COMMA || eTok == RPAREN )
921 bError2 = sal_False;
922 }
923 if( bError2 )
924 {
925 Error( SbERR_EXPECTED, RPAREN );
926 break;
927 }
928 }
929 if( eTok == RPAREN )
930 break;
931 }
932 }
933 TypeDecl( *pDef );
934 if( eType != SbxVARIANT && pDef->GetType() != eType )
935 Error( SbERR_BAD_DECLARATION, aName );
936 // if( pDef->GetType() == SbxOBJECT )
937 // pDef->SetType( SbxVARIANT ),
938 // Error( SbERR_SYNTAX );
939 if( pDef->GetType() == SbxVARIANT && !( bFunc || bProp ) )
940 pDef->SetType( SbxEMPTY );
941 return pDef;
942 }
943
944 // DECLARE
945
Declare()946 void SbiParser::Declare()
947 {
948 DefDeclare( sal_False );
949 }
950
DefDeclare(sal_Bool bPrivate)951 void SbiParser::DefDeclare( sal_Bool bPrivate )
952 {
953 Next();
954 if( eCurTok != SUB && eCurTok != FUNCTION )
955 Error( SbERR_UNEXPECTED, eCurTok );
956 else
957 {
958 bool bFunction = (eCurTok == FUNCTION);
959
960 SbiProcDef* pDef = ProcDecl( sal_True );
961 if( pDef )
962 {
963 if( !pDef->GetLib().Len() )
964 Error( SbERR_EXPECTED, LIB );
965 // gibts den schon?
966 SbiSymDef* pOld = aPublics.Find( pDef->GetName() );
967 if( pOld )
968 {
969 SbiProcDef* p = pOld->GetProcDef();
970 if( !p )
971 {
972 // Als Variable deklariert
973 Error( SbERR_BAD_DECLARATION, pDef->GetName() );
974 delete pDef;
975 pDef = NULL;
976 }
977 else
978 pDef->Match( p );
979 }
980 else
981 aPublics.Add( pDef );
982
983 if ( pDef )
984 {
985 pDef->SetPublic( !bPrivate );
986
987 // New declare handling
988 if( pDef->GetLib().Len() > 0 )
989 {
990 if( bNewGblDefs && nGblChain == 0 )
991 {
992 nGblChain = aGen.Gen( _JUMP, 0 );
993 bNewGblDefs = sal_False;
994 }
995
996 sal_uInt16 nSavLine = nLine;
997 aGen.Statement();
998 pDef->Define();
999 pDef->SetLine1( nSavLine );
1000 pDef->SetLine2( nSavLine );
1001
1002 SbiSymPool& rPool = pDef->GetParams();
1003 sal_uInt16 nParCount = rPool.GetSize();
1004
1005 SbxDataType eType = pDef->GetType();
1006 if( bFunction )
1007 aGen.Gen( _PARAM, 0, sal::static_int_cast< sal_uInt16 >( eType ) );
1008
1009 if( nParCount > 1 )
1010 {
1011 aGen.Gen( _ARGC );
1012
1013 for( sal_uInt16 i = 1 ; i < nParCount ; ++i )
1014 {
1015 SbiSymDef* pParDef = rPool.Get( i );
1016 SbxDataType eParType = pParDef->GetType();
1017
1018 aGen.Gen( _PARAM, i, sal::static_int_cast< sal_uInt16 >( eParType ) );
1019 aGen.Gen( _ARGV );
1020
1021 sal_uInt16 nTyp = sal::static_int_cast< sal_uInt16 >( pParDef->GetType() );
1022 if( pParDef->IsByVal() )
1023 {
1024 // Reset to avoid additional byval in call to wrapper function
1025 pParDef->SetByVal( sal_False );
1026 nTyp |= 0x8000;
1027 }
1028 aGen.Gen( _ARGTYP, nTyp );
1029 }
1030 }
1031
1032 aGen.Gen( _LIB, aGblStrings.Add( pDef->GetLib() ) );
1033
1034 SbiOpcode eOp = pDef->IsCdecl() ? _CALLC : _CALL;
1035 sal_uInt16 nId = pDef->GetId();
1036 if( pDef->GetAlias().Len() )
1037 nId = ( nId & 0x8000 ) | aGblStrings.Add( pDef->GetAlias() );
1038 if( nParCount > 1 )
1039 nId |= 0x8000;
1040 aGen.Gen( eOp, nId, sal::static_int_cast< sal_uInt16 >( eType ) );
1041
1042 if( bFunction )
1043 aGen.Gen( _PUT );
1044
1045 aGen.Gen( _LEAVE );
1046 }
1047 }
1048 }
1049 }
1050 }
1051
1052 // Aufruf einer SUB oder FUNCTION
1053
Call()1054 void SbiParser::Call()
1055 {
1056 String aName( aSym );
1057 SbiExpression aVar( this, SbSYMBOL );
1058 aVar.Gen( FORCE_CALL );
1059 aGen.Gen( _GET );
1060 }
1061
1062 // SUB/FUNCTION
1063
SubFunc()1064 void SbiParser::SubFunc()
1065 {
1066 DefProc( sal_False, sal_False );
1067 }
1068
1069 // Einlesen einer Prozedur
1070
1071 sal_Bool runsInSetup( void );
1072
DefProc(sal_Bool bStatic,sal_Bool bPrivate)1073 void SbiParser::DefProc( sal_Bool bStatic, sal_Bool bPrivate )
1074 {
1075 sal_uInt16 l1 = nLine, l2 = nLine;
1076 sal_Bool bSub = sal_Bool( eCurTok == SUB );
1077 sal_Bool bProperty = sal_Bool( eCurTok == PROPERTY );
1078 PropertyMode ePropertyMode = PROPERTY_MODE_NONE;
1079 if( bProperty )
1080 {
1081 Next();
1082 if( eCurTok == GET )
1083 ePropertyMode = PROPERTY_MODE_GET;
1084 else if( eCurTok == LET )
1085 ePropertyMode = PROPERTY_MODE_LET;
1086 else if( eCurTok == SET )
1087 ePropertyMode = PROPERTY_MODE_SET;
1088 else
1089 Error( SbERR_EXPECTED, "Get or Let or Set" );
1090 }
1091
1092 SbiToken eExit = eCurTok;
1093 SbiProcDef* pDef = ProcDecl( sal_False );
1094 if( !pDef )
1095 return;
1096 pDef->setPropertyMode( ePropertyMode );
1097
1098 // Ist die Proc bereits deklariert?
1099 SbiSymDef* pOld = aPublics.Find( pDef->GetName() );
1100 if( pOld )
1101 {
1102 bool bError_ = false;
1103
1104 pProc = pOld->GetProcDef();
1105 if( !pProc )
1106 {
1107 // Als Variable deklariert
1108 Error( SbERR_BAD_DECLARATION, pDef->GetName() );
1109 delete pDef;
1110 pProc = NULL;
1111 bError_ = true;
1112 }
1113 // #100027: Multiple declaration -> Error
1114 // #112787: Not for setup, REMOVE for 8
1115 else if( !runsInSetup() && pProc->IsUsedForProcDecl() )
1116 {
1117 PropertyMode ePropMode = pDef->getPropertyMode();
1118 if( ePropMode == PROPERTY_MODE_NONE || ePropMode == pProc->getPropertyMode() )
1119 {
1120 Error( SbERR_PROC_DEFINED, pDef->GetName() );
1121 delete pDef;
1122 pProc = NULL;
1123 bError_ = true;
1124 }
1125 }
1126
1127 if( !bError_ )
1128 {
1129 pDef->Match( pProc );
1130 pProc = pDef;
1131 }
1132 }
1133 else
1134 aPublics.Add( pDef ), pProc = pDef;
1135
1136 if( !pProc )
1137 return;
1138 pProc->SetPublic( !bPrivate );
1139
1140 // Nun setzen wir die Suchhierarchie fuer Symbole sowie die aktuelle
1141 // Prozedur.
1142 aPublics.SetProcId( pProc->GetId() );
1143 pProc->GetParams().SetParent( &aPublics );
1144 if( bStatic )
1145 {
1146 if ( bVBASupportOn )
1147 pProc->SetStatic( sal_True );
1148 else
1149 Error( SbERR_NOT_IMPLEMENTED ); // STATIC SUB ...
1150 }
1151 else
1152 {
1153 pProc->SetStatic( sal_False );
1154 }
1155 // Normalfall: Lokale Variable->Parameter->Globale Variable
1156 pProc->GetLocals().SetParent( &pProc->GetParams() );
1157 pPool = &pProc->GetLocals();
1158
1159 pProc->Define();
1160 OpenBlock( eExit );
1161 StmntBlock( bSub ? ENDSUB : (bProperty ? ENDPROPERTY : ENDFUNC) );
1162 l2 = nLine;
1163 pProc->SetLine1( l1 );
1164 pProc->SetLine2( l2 );
1165 pPool = &aPublics;
1166 aPublics.SetProcId( 0 );
1167 // Offene Labels?
1168 pProc->GetLabels().CheckRefs();
1169 CloseBlock();
1170 aGen.Gen( _LEAVE );
1171 pProc = NULL;
1172 }
1173
1174 // STATIC variable|procedure
1175
Static()1176 void SbiParser::Static()
1177 {
1178 DefStatic( sal_False );
1179 }
1180
DefStatic(sal_Bool bPrivate)1181 void SbiParser::DefStatic( sal_Bool bPrivate )
1182 {
1183 switch( Peek() )
1184 {
1185 case SUB:
1186 case FUNCTION:
1187 case PROPERTY:
1188 // End global chain if necessary (not done in
1189 // SbiParser::Parse() under these conditions
1190 if( bNewGblDefs && nGblChain == 0 )
1191 {
1192 nGblChain = aGen.Gen( _JUMP, 0 );
1193 bNewGblDefs = sal_False;
1194 }
1195 Next();
1196 DefProc( sal_True, bPrivate );
1197 break;
1198 default: {
1199 if( !pProc )
1200 Error( SbERR_NOT_IN_SUBR );
1201 // Pool umsetzen, damit STATIC-Deklarationen im globalen
1202 // Pool landen
1203 SbiSymPool* p = pPool; pPool = &aPublics;
1204 DefVar( _STATIC, sal_True );
1205 pPool = p;
1206 } break;
1207 }
1208 }
1209
1210