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 :
21 : #include "sbcomp.hxx"
22 : #include <stdio.h>
23 : #include <string.h>
24 : #include <ctype.h>
25 :
26 : // All symbol names are laid down int the symbol-pool's stringpool, so that
27 : // all symbols are handled in the same case. On saving the code-image, the
28 : // global stringpool with the respective symbols is also saved.
29 : // The local stringpool holds all the symbols that don't move to the image
30 : // (labels, constant names etc.).
31 :
32 : /***************************************************************************
33 : |*
34 : |* SbiStringPool
35 : |*
36 : ***************************************************************************/
37 :
38 342 : SbiStringPool::SbiStringPool( SbiParser* p )
39 : {
40 342 : pParser = p;
41 342 : }
42 :
43 342 : SbiStringPool::~SbiStringPool()
44 342 : {}
45 :
46 6314 : const OUString& SbiStringPool::Find( sal_uInt32 n ) const
47 : {
48 6314 : if( n == 0 || n > aData.size() )
49 0 : return aEmpty; //hack, returning a reference to a simulation of null
50 : else
51 6314 : return aData[n - 1];
52 : }
53 :
54 9428 : short SbiStringPool::Add( const OUString& rVal, bool bNoCase )
55 : {
56 9428 : sal_uInt32 n = aData.size();
57 832194 : for( sal_uInt32 i = 0; i < n; ++i )
58 : {
59 826457 : OUString& p = aData[i];
60 1652914 : if( ( bNoCase && p == rVal )
61 1649223 : || ( !bNoCase && p.equalsIgnoreAsciiCase( rVal ) ) )
62 3691 : return i+1;
63 : }
64 :
65 5737 : aData.push_back(rVal);
66 5737 : return (short) ++n;
67 : }
68 :
69 83 : short SbiStringPool::Add( double n, SbxDataType t )
70 : {
71 : char buf[ 40 ];
72 83 : switch( t )
73 : {
74 0 : case SbxINTEGER: snprintf( buf, sizeof(buf), "%d", (short) n ); break;
75 16 : case SbxLONG: snprintf( buf, sizeof(buf), "%ld", (long) n ); break;
76 0 : case SbxSINGLE: snprintf( buf, sizeof(buf), "%.6g", (float) n ); break;
77 67 : case SbxDOUBLE: snprintf( buf, sizeof(buf), "%.16g", n ); break;
78 0 : default: break;
79 : }
80 83 : return Add( OUString::createFromAscii( buf ) );
81 : }
82 :
83 : /***************************************************************************
84 : |*
85 : |* SbiSymPool
86 : |*
87 : ***************************************************************************/
88 :
89 4226 : SbiSymPool::SbiSymPool( SbiStringPool& r, SbiSymScope s ) : rStrings( r )
90 : {
91 4226 : pParser = r.GetParser();
92 4226 : eScope = s;
93 4226 : pParent = NULL;
94 : nCur =
95 4226 : nProcId = 0;
96 4226 : }
97 :
98 4226 : SbiSymPool::~SbiSymPool()
99 4226 : {}
100 :
101 :
102 171 : SbiSymDef* SbiSymPool::First()
103 : {
104 171 : nCur = (sal_uInt16) -1;
105 171 : return Next();
106 : }
107 :
108 2175 : SbiSymDef* SbiSymPool::Next()
109 : {
110 2175 : if( ++nCur >= aData.size() )
111 191 : return NULL;
112 : else
113 1984 : return aData[ nCur ];
114 : }
115 :
116 :
117 2736 : SbiSymDef* SbiSymPool::AddSym( const OUString& rName )
118 : {
119 2736 : SbiSymDef* p = new SbiSymDef( rName );
120 2736 : p->nPos = aData.size();
121 2736 : p->nId = rStrings.Add( rName );
122 2736 : p->nProcId = nProcId;
123 2736 : p->pIn = this;
124 2736 : aData.insert( aData.begin() + p->nPos, p );
125 2736 : return p;
126 : }
127 :
128 715 : SbiProcDef* SbiSymPool::AddProc( const OUString& rName )
129 : {
130 715 : SbiProcDef* p = new SbiProcDef( pParser, rName );
131 715 : p->nPos = aData.size();
132 715 : p->nId = rStrings.Add( rName );
133 : // procs are always local
134 715 : p->nProcId = 0;
135 715 : p->pIn = this;
136 715 : aData.insert( aData.begin() + p->nPos, p );
137 715 : return p;
138 : }
139 :
140 : // adding an externally constructed symbol definition
141 :
142 2486 : void SbiSymPool::Add( SbiSymDef* pDef )
143 : {
144 2486 : if( pDef && pDef->pIn != this )
145 : {
146 2486 : if( pDef->pIn )
147 : {
148 : #ifdef DBG_UTIL
149 :
150 : pParser->Error( SbERR_INTERNAL_ERROR, "Dbl Pool" );
151 : #endif
152 2486 : return;
153 : }
154 :
155 2486 : pDef->nPos = aData.size();
156 2486 : if( !pDef->nId )
157 : {
158 : // A unique name must be created in the string pool
159 : // for static variables (Form ProcName:VarName)
160 2486 : OUString aName( pDef->aName );
161 2486 : if( pDef->IsStatic() )
162 : {
163 0 : aName = pParser->aGblStrings.Find( nProcId );
164 0 : aName += ":";
165 0 : aName += pDef->aName;
166 : }
167 2486 : pDef->nId = rStrings.Add( aName );
168 : }
169 :
170 2486 : if( !pDef->GetProcDef() )
171 : {
172 2299 : pDef->nProcId = nProcId;
173 : }
174 2486 : pDef->pIn = this;
175 2486 : aData.insert( aData.begin() + pDef->nPos, pDef );
176 : }
177 : }
178 :
179 :
180 31514 : SbiSymDef* SbiSymPool::Find( const OUString& rName ) const
181 : {
182 31514 : sal_uInt16 nCount = aData.size();
183 246764 : for( sal_uInt16 i = 0; i < nCount; i++ )
184 : {
185 225813 : SbiSymDef* p = aData[ nCount - i - 1 ];
186 451626 : if( ( !p->nProcId || ( p->nProcId == nProcId)) &&
187 225813 : ( p->aName.equalsIgnoreAsciiCase(rName)))
188 : {
189 10563 : return p;
190 : }
191 : }
192 20951 : if( pParent )
193 : {
194 18052 : return pParent->Find( rName );
195 : }
196 : else
197 : {
198 2899 : return NULL;
199 : }
200 : }
201 :
202 :
203 0 : SbiSymDef* SbiSymPool::FindId( sal_uInt16 n ) const
204 : {
205 0 : for( sal_uInt16 i = 0; i < aData.size(); i++ )
206 : {
207 0 : SbiSymDef* p = aData[ i ];
208 0 : if( p->nId == n && ( !p->nProcId || ( p->nProcId == nProcId ) ) )
209 : {
210 0 : return p;
211 : }
212 : }
213 0 : if( pParent )
214 : {
215 0 : return pParent->FindId( n );
216 : }
217 : else
218 : {
219 0 : return NULL;
220 : }
221 : }
222 :
223 : // find via position (from 0)
224 :
225 2324 : SbiSymDef* SbiSymPool::Get( sal_uInt16 n ) const
226 : {
227 2324 : if( n >= aData.size() )
228 : {
229 20 : return NULL;
230 : }
231 : else
232 : {
233 2304 : return aData[ n ];
234 : }
235 : }
236 :
237 52 : sal_uInt32 SbiSymPool::Define( const OUString& rName )
238 : {
239 52 : SbiSymDef* p = Find( rName );
240 52 : if( p )
241 : {
242 52 : if( p->IsDefined() )
243 : {
244 0 : pParser->Error( SbERR_LABEL_DEFINED, rName );
245 : }
246 : }
247 : else
248 : {
249 0 : p = AddSym( rName );
250 : }
251 52 : return p->Define();
252 : }
253 :
254 52 : sal_uInt32 SbiSymPool::Reference( const OUString& rName )
255 : {
256 52 : SbiSymDef* p = Find( rName );
257 52 : if( !p )
258 : {
259 52 : p = AddSym( rName );
260 : }
261 : // to be sure
262 52 : pParser->aGen.GenStmnt();
263 52 : return p->Reference();
264 : }
265 :
266 :
267 395 : void SbiSymPool::CheckRefs()
268 : {
269 447 : for( sal_uInt16 i = 0; i < aData.size(); i++ )
270 : {
271 52 : SbiSymDef* p = aData[ i ];
272 52 : if( !p->IsDefined() )
273 : {
274 0 : pParser->Error( SbERR_UNDEF_LABEL, p->GetName() );
275 : }
276 : }
277 395 : }
278 :
279 : /***************************************************************************
280 : |*
281 : |* symbol definitions
282 : |*
283 : ***************************************************************************/
284 :
285 6146 : SbiSymDef::SbiSymDef( const OUString& rName ) : aName( rName )
286 : {
287 6146 : eType = SbxEMPTY;
288 6146 : nDims = 0;
289 6146 : nTypeId = 0;
290 6146 : nProcId = 0;
291 6146 : nId = 0;
292 6146 : nPos = 0;
293 6146 : nLen = 0;
294 6146 : nChain = 0;
295 : bAs =
296 : bNew =
297 : bStatic =
298 : bOpt =
299 : bParamArray =
300 : bWithEvents =
301 : bWithBrackets =
302 : bByVal =
303 : bChained =
304 6146 : bGlobal = false;
305 : pIn =
306 6146 : pPool = NULL;
307 6146 : nDefaultId = 0;
308 6146 : nFixedStringLength = -1;
309 6146 : }
310 :
311 15973 : SbiSymDef::~SbiSymDef()
312 : {
313 6146 : delete pPool;
314 9827 : }
315 :
316 9464 : SbiProcDef* SbiSymDef::GetProcDef()
317 : {
318 9464 : return NULL;
319 : }
320 :
321 10808 : SbiConstDef* SbiSymDef::GetConstDef()
322 : {
323 10808 : return NULL;
324 : }
325 :
326 :
327 2714 : const OUString& SbiSymDef::GetName()
328 : {
329 2714 : if( pIn )
330 : {
331 602 : aName = pIn->rStrings.Find( nId );
332 : }
333 2714 : return aName;
334 : }
335 :
336 :
337 8458 : void SbiSymDef::SetType( SbxDataType t )
338 : {
339 8458 : if( t == SbxVARIANT && pIn )
340 : {
341 2577 : sal_Unicode cu = aName[0];
342 2577 : if( cu < 256 )
343 : {
344 2577 : char ch = (char)cu;
345 2577 : if( ch == '_' )
346 : {
347 0 : ch = 'Z';
348 : }
349 2577 : int ch2 = toupper( ch );
350 2577 : unsigned char c = (unsigned char)ch2;
351 2577 : if( c > 0 && c < 128 )
352 : {
353 2577 : int nIndex = ch2 - 'A';
354 : assert(nIndex >= 0 && nIndex < N_DEF_TYPES);
355 2577 : if (nIndex >= 0 && nIndex < N_DEF_TYPES)
356 2577 : t = pIn->pParser->eDefTypes[nIndex];
357 : }
358 : }
359 : }
360 8458 : eType = t;
361 8458 : }
362 :
363 : // construct a backchain, if not yet defined
364 : // the value that shall be stored as an operand is returned
365 :
366 52 : sal_uInt32 SbiSymDef::Reference()
367 : {
368 52 : if( !bChained )
369 : {
370 52 : sal_uInt32 n = nChain;
371 52 : nChain = pIn->pParser->aGen.GetOffset();
372 52 : return n;
373 : }
374 0 : else return nChain;
375 : }
376 :
377 :
378 447 : sal_uInt32 SbiSymDef::Define()
379 : {
380 447 : sal_uInt32 n = pIn->pParser->aGen.GetPC();
381 447 : pIn->pParser->aGen.GenStmnt();
382 447 : if( nChain )
383 : {
384 52 : pIn->pParser->aGen.BackChain( nChain );
385 : }
386 447 : nChain = n;
387 447 : bChained = true;
388 447 : return nChain;
389 : }
390 :
391 : // A symbol definition may have its own pool. This is the case
392 : // for objects and procedures (local variable)
393 :
394 3533 : SbiSymPool& SbiSymDef::GetPool()
395 : {
396 3533 : if( !pPool )
397 : {
398 383 : pPool = new SbiSymPool( pIn->pParser->aGblStrings, SbLOCAL ); // is dumped
399 : }
400 3533 : return *pPool;
401 : }
402 :
403 21476 : SbiSymScope SbiSymDef::GetScope() const
404 : {
405 21476 : return pIn ? pIn->GetScope() : SbLOCAL;
406 : }
407 :
408 :
409 : // The procedure definition has three pools:
410 : // 1) aParams: is filled by the definition. Contains the
411 : // parameters' names, like they're used inside the body.
412 : // The first element is the return value.
413 : // 2) pPool: all local variables
414 : // 3) aLabels: labels
415 :
416 1110 : SbiProcDef::SbiProcDef( SbiParser* pParser, const OUString& rName,
417 : bool bProcDecl )
418 : : SbiSymDef( rName )
419 : , aParams( pParser->aGblStrings, SbPARAM ) // is dumped
420 : , aLabels( pParser->aLclStrings, SbLOCAL ) // is not dumped
421 1110 : , mbProcDecl( bProcDecl )
422 : {
423 1110 : aParams.SetParent( &pParser->aPublics );
424 1110 : pPool = new SbiSymPool( pParser->aGblStrings, SbLOCAL );
425 1110 : pPool->SetParent( &aParams );
426 : nLine1 =
427 1110 : nLine2 = 0;
428 1110 : mePropMode = PROPERTY_MODE_NONE;
429 1110 : bPublic = true;
430 1110 : bCdecl = false;
431 1110 : bStatic = false;
432 : // For return values the first element of the parameter
433 : // list is always defined with name and type of the proc
434 1110 : aParams.AddSym( aName );
435 1110 : }
436 :
437 2220 : SbiProcDef::~SbiProcDef()
438 2220 : {}
439 :
440 2780 : SbiProcDef* SbiProcDef::GetProcDef()
441 : {
442 2780 : return this;
443 : }
444 :
445 1794 : void SbiProcDef::SetType( SbxDataType t )
446 : {
447 1794 : SbiSymDef::SetType( t );
448 1794 : aParams.Get( 0 )->SetType( eType );
449 1794 : }
450 :
451 : // match with a forward-declaration
452 : // if the match is OK, pOld is replaced by this in the pool
453 : // pOld is deleted in any case!
454 :
455 208 : void SbiProcDef::Match( SbiProcDef* pOld )
456 : {
457 208 : SbiSymDef *pn=NULL;
458 : // parameter 0 is the function name
459 : sal_uInt16 i;
460 370 : for( i = 1; i < aParams.GetSize(); i++ )
461 : {
462 162 : SbiSymDef* po = pOld->aParams.Get( i );
463 162 : pn = aParams.Get( i );
464 : // no type matching - that is done during running
465 : // but is it maybe called with too little parameters?
466 162 : if( !po && !pn->IsOptional() && !pn->IsParamArray() )
467 : {
468 0 : break;
469 : }
470 162 : pOld->aParams.Next();
471 : }
472 :
473 208 : if( pn && i < aParams.GetSize() && pOld->pIn )
474 : {
475 : // mark the whole line
476 0 : pOld->pIn->GetParser()->SetCol1( 0 );
477 0 : pOld->pIn->GetParser()->Error( SbERR_BAD_DECLARATION, aName );
478 : }
479 208 : if( !pIn && pOld->pIn )
480 : {
481 : // Replace old entry with the new one
482 208 : pOld->pIn->aData[ pOld->nPos ] = this;
483 208 : nPos = pOld->nPos;
484 208 : nId = pOld->nId;
485 208 : pIn = pOld->pIn;
486 : }
487 208 : delete pOld;
488 208 : }
489 :
490 395 : void SbiProcDef::setPropertyMode( PropertyMode ePropMode )
491 : {
492 395 : mePropMode = ePropMode;
493 395 : if( mePropMode != PROPERTY_MODE_NONE )
494 : {
495 : // Prop name = original scanned procedure name
496 0 : maPropName = aName;
497 :
498 : // CompleteProcName includes "Property xxx "
499 : // to avoid conflicts with other symbols
500 0 : OUString aCompleteProcName = "Property ";
501 0 : switch( mePropMode )
502 : {
503 0 : case PROPERTY_MODE_GET: aCompleteProcName += "Get "; break;
504 0 : case PROPERTY_MODE_LET: aCompleteProcName += "Let "; break;
505 0 : case PROPERTY_MODE_SET: aCompleteProcName += "Set "; break;
506 0 : case PROPERTY_MODE_NONE: OSL_FAIL( "Illegal PropertyMode PROPERTY_MODE_NONE" ); break;
507 : }
508 0 : aCompleteProcName += aName;
509 0 : aName = aCompleteProcName;
510 : }
511 395 : }
512 :
513 :
514 :
515 1355 : SbiConstDef::SbiConstDef( const OUString& rName )
516 1355 : : SbiSymDef( rName )
517 : {
518 1355 : nVal = 0; eType = SbxINTEGER;
519 1355 : }
520 :
521 60 : void SbiConstDef::Set( double n, SbxDataType t )
522 : {
523 60 : aVal = ""; nVal = n; eType = t;
524 60 : }
525 :
526 1295 : void SbiConstDef::Set( const OUString& n )
527 : {
528 1295 : aVal = n; nVal = 0; eType = SbxSTRING;
529 1295 : }
530 :
531 2710 : SbiConstDef::~SbiConstDef()
532 2710 : {}
533 :
534 383 : SbiConstDef* SbiConstDef::GetConstDef()
535 : {
536 383 : return this;
537 : }
538 :
539 8452 : SbiSymbols::~SbiSymbols()
540 : {
541 10163 : for( const_iterator it = begin(); it != end(); ++it )
542 : {
543 5937 : delete *it;
544 : }
545 4226 : };
546 :
547 :
548 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|