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