Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / basic / source / comp / symtbl.cxx
blob005ae381ebcc9c6b7b12548e68367a8c360cbd0a
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 .
21 #include "sbcomp.hxx"
22 #include <stdio.h>
23 #include <string.h>
24 #include <ctype.h>
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.).
32 /***************************************************************************
34 |* SbiStringPool
36 ***************************************************************************/
38 SbiStringPool::SbiStringPool( SbiParser* p )
40 pParser = p;
43 SbiStringPool::~SbiStringPool()
46 const rtl::OUString& SbiStringPool::Find( sal_uInt32 n ) const
48 if( n == 0 || n > aData.size() )
49 return aEmpty; //hack, returning a reference to a simulation of null
50 else
51 return aData[n - 1];
54 short SbiStringPool::Add( const OUString& rVal, bool bNoCase )
56 sal_uInt32 n = aData.size();
57 for( sal_uInt32 i = 0; i < n; ++i )
59 OUString& p = aData[i];
60 if( ( bNoCase && p == rVal )
61 || ( !bNoCase && p.equalsIgnoreAsciiCase( rVal ) ) )
62 return i+1;
65 aData.push_back(rVal);
66 return (short) ++n;
69 short SbiStringPool::Add( double n, SbxDataType t )
71 char buf[ 40 ];
72 switch( t )
74 case SbxINTEGER: snprintf( buf, sizeof(buf), "%d", (short) n ); break;
75 case SbxLONG: snprintf( buf, sizeof(buf), "%ld", (long) n ); break;
76 case SbxSINGLE: snprintf( buf, sizeof(buf), "%.6g", (float) n ); break;
77 case SbxDOUBLE: snprintf( buf, sizeof(buf), "%.16g", n ); break;
78 default: break;
80 return Add( rtl::OUString::createFromAscii( buf ) );
83 /***************************************************************************
85 |* SbiSymPool
87 ***************************************************************************/
89 SbiSymPool::SbiSymPool( SbiStringPool& r, SbiSymScope s ) : rStrings( r )
91 pParser = r.GetParser();
92 eScope = s;
93 pParent = NULL;
94 nCur =
95 nProcId = 0;
98 SbiSymPool::~SbiSymPool()
102 SbiSymDef* SbiSymPool::First()
104 nCur = (sal_uInt16) -1;
105 return Next();
108 SbiSymDef* SbiSymPool::Next()
110 if( ++nCur >= aData.size() )
111 return NULL;
112 else
113 return aData[ nCur ];
117 SbiSymDef* SbiSymPool::AddSym( const OUString& rName )
119 SbiSymDef* p = new SbiSymDef( rName );
120 p->nPos = aData.size();
121 p->nId = rStrings.Add( rName );
122 p->nProcId = nProcId;
123 p->pIn = this;
124 aData.insert( aData.begin() + p->nPos, p );
125 return p;
128 SbiProcDef* SbiSymPool::AddProc( const OUString& rName )
130 SbiProcDef* p = new SbiProcDef( pParser, rName );
131 p->nPos = aData.size();
132 p->nId = rStrings.Add( rName );
133 // procs are always local
134 p->nProcId = 0;
135 p->pIn = this;
136 aData.insert( aData.begin() + p->nPos, p );
137 return p;
140 // adding an externally constructed symbol definition
142 void SbiSymPool::Add( SbiSymDef* pDef )
144 if( pDef && pDef->pIn != this )
146 if( pDef->pIn )
148 #ifdef DBG_UTIL
150 pParser->Error( SbERR_INTERNAL_ERROR, "Dbl Pool" );
151 #endif
152 return;
155 pDef->nPos = aData.size();
156 if( !pDef->nId )
158 // A unique name must be created in the string pool
159 // for static variables (Form ProcName:VarName)
160 OUString aName( pDef->aName );
161 if( pDef->IsStatic() )
163 aName = pParser->aGblStrings.Find( nProcId );
164 aName += ":";
165 aName += pDef->aName;
167 pDef->nId = rStrings.Add( aName );
170 if( !pDef->GetProcDef() )
172 pDef->nProcId = nProcId;
174 pDef->pIn = this;
175 aData.insert( aData.begin() + pDef->nPos, pDef );
180 SbiSymDef* SbiSymPool::Find( const OUString& rName ) const
182 sal_uInt16 nCount = aData.size();
183 for( sal_uInt16 i = 0; i < nCount; i++ )
185 SbiSymDef* p = aData[ nCount - i - 1 ];
186 if( ( !p->nProcId || ( p->nProcId == nProcId)) &&
187 ( p->aName.equalsIgnoreAsciiCase(rName)))
189 return p;
192 if( pParent )
194 return pParent->Find( rName );
196 else
198 return NULL;
203 SbiSymDef* SbiSymPool::FindId( sal_uInt16 n ) const
205 for( sal_uInt16 i = 0; i < aData.size(); i++ )
207 SbiSymDef* p = aData[ i ];
208 if( p->nId == n && ( !p->nProcId || ( p->nProcId == nProcId ) ) )
210 return p;
213 if( pParent )
215 return pParent->FindId( n );
217 else
219 return NULL;
223 // find via position (from 0)
225 SbiSymDef* SbiSymPool::Get( sal_uInt16 n ) const
227 if( n >= aData.size() )
229 return NULL;
231 else
233 return aData[ n ];
237 sal_uInt32 SbiSymPool::Define( const OUString& rName )
239 SbiSymDef* p = Find( rName );
240 if( p )
242 if( p->IsDefined() )
244 pParser->Error( SbERR_LABEL_DEFINED, rName );
247 else
249 p = AddSym( rName );
251 return p->Define();
254 sal_uInt32 SbiSymPool::Reference( const OUString& rName )
256 SbiSymDef* p = Find( rName );
257 if( !p )
259 p = AddSym( rName );
261 // to be sure
262 pParser->aGen.GenStmnt();
263 return p->Reference();
267 void SbiSymPool::CheckRefs()
269 for( sal_uInt16 i = 0; i < aData.size(); i++ )
271 SbiSymDef* p = aData[ i ];
272 if( !p->IsDefined() )
274 pParser->Error( SbERR_UNDEF_LABEL, p->GetName() );
279 /***************************************************************************
281 |* symbol definitions
283 ***************************************************************************/
285 SbiSymDef::SbiSymDef( const OUString& rName ) : aName( rName )
287 eType = SbxEMPTY;
288 nDims = 0;
289 nTypeId = 0;
290 nProcId = 0;
291 nId = 0;
292 nPos = 0;
293 nLen = 0;
294 nChain = 0;
295 bAs =
296 bNew =
297 bStatic =
298 bOpt =
299 bParamArray =
300 bWithEvents =
301 bWithBrackets =
302 bByVal =
303 bChained =
304 bGlobal = false;
305 pIn =
306 pPool = NULL;
307 nDefaultId = 0;
308 nFixedStringLength = -1;
311 SbiSymDef::~SbiSymDef()
313 delete pPool;
316 SbiProcDef* SbiSymDef::GetProcDef()
318 return NULL;
321 SbiConstDef* SbiSymDef::GetConstDef()
323 return NULL;
327 const OUString& SbiSymDef::GetName()
329 if( pIn )
331 aName = pIn->rStrings.Find( nId );
333 return aName;
337 void SbiSymDef::SetType( SbxDataType t )
339 if( t == SbxVARIANT && pIn )
341 sal_Unicode cu = aName[0];
342 if( cu < 256 )
344 char ch = (char)cu;
345 if( ch == '_' )
347 ch = 'Z';
349 int ch2 = toupper( ch );
350 unsigned char c = (unsigned char)ch2;
351 if( c > 0 && c < 128 )
353 t = pIn->pParser->eDefTypes[ ch2 - 'A' ];
357 eType = t;
360 // construct a backchain, if not yet defined
361 // the value that shall be stored as an operand is returned
363 sal_uInt32 SbiSymDef::Reference()
365 if( !bChained )
367 sal_uInt32 n = nChain;
368 nChain = pIn->pParser->aGen.GetOffset();
369 return n;
371 else return nChain;
375 sal_uInt32 SbiSymDef::Define()
377 sal_uInt32 n = pIn->pParser->aGen.GetPC();
378 pIn->pParser->aGen.GenStmnt();
379 if( nChain )
381 pIn->pParser->aGen.BackChain( nChain );
383 nChain = n;
384 bChained = true;
385 return nChain;
388 // A symbol definition may have its own pool. This is the caseDies ist
389 // for objects and procedures (local variable)
391 SbiSymPool& SbiSymDef::GetPool()
393 if( !pPool )
395 pPool = new SbiSymPool( pIn->pParser->aGblStrings, SbLOCAL ); // is dumped
397 return *pPool;
400 SbiSymScope SbiSymDef::GetScope() const
402 return pIn ? pIn->GetScope() : SbLOCAL;
406 // The procedure definition has three pools:
407 // 1) aParams: is filled by the definition. Contains the
408 // parameters' names, like they're used inside the body.
409 // The first element is the return value.
410 // 2) pPool: all local variables
411 // 3) aLabels: labels
413 SbiProcDef::SbiProcDef( SbiParser* pParser, const OUString& rName,
414 bool bProcDecl )
415 : SbiSymDef( rName )
416 , aParams( pParser->aGblStrings, SbPARAM ) // is dumped
417 , aLabels( pParser->aLclStrings, SbLOCAL ) // is not dumped
418 , mbProcDecl( bProcDecl )
420 aParams.SetParent( &pParser->aPublics );
421 pPool = new SbiSymPool( pParser->aGblStrings, SbLOCAL );
422 pPool->SetParent( &aParams );
423 nLine1 =
424 nLine2 = 0;
425 mePropMode = PROPERTY_MODE_NONE;
426 bPublic = true;
427 bCdecl = false;
428 bStatic = false;
429 // For return values the first element of the parameter
430 // list is always defined with name and type of the proc
431 aParams.AddSym( aName );
434 SbiProcDef::~SbiProcDef()
437 SbiProcDef* SbiProcDef::GetProcDef()
439 return this;
442 void SbiProcDef::SetType( SbxDataType t )
444 SbiSymDef::SetType( t );
445 aParams.Get( 0 )->SetType( eType );
448 // match with a forward-declaration
449 // if the match is OK, pOld is replaced by this in the pool
450 // pOld is deleted in any case!
452 void SbiProcDef::Match( SbiProcDef* pOld )
454 SbiSymDef* po, *pn=NULL;
455 // parameter 0 is the function name
456 sal_uInt16 i;
457 for( i = 1; i < aParams.GetSize(); i++ )
459 po = pOld->aParams.Get( i );
460 pn = aParams.Get( i );
461 // no type matching - that is done during running
462 // but is it maybe called with too little parameters?
463 if( !po && !pn->IsOptional() && !pn->IsParamArray() )
465 break;
467 po = pOld->aParams.Next();
470 if( pn && i < aParams.GetSize() && pOld->pIn )
472 // mark the whole line
473 pOld->pIn->GetParser()->SetCol1( 0 );
474 pOld->pIn->GetParser()->Error( SbERR_BAD_DECLARATION, aName );
476 if( !pIn && pOld->pIn )
478 // Replace old entry with the new one
479 pOld->pIn->aData[ pOld->nPos ] = this;
480 nPos = pOld->nPos;
481 nId = pOld->nId;
482 pIn = pOld->pIn;
484 delete pOld;
487 void SbiProcDef::setPropertyMode( PropertyMode ePropMode )
489 mePropMode = ePropMode;
490 if( mePropMode != PROPERTY_MODE_NONE )
492 // Prop name = original scanned procedure name
493 maPropName = aName;
495 // CompleteProcName includes "Property xxx "
496 // to avoid conflicts with other symbols
497 OUString aCompleteProcName = "Property ";
498 switch( mePropMode )
500 case PROPERTY_MODE_GET: aCompleteProcName += "Get "; break;
501 case PROPERTY_MODE_LET: aCompleteProcName += "Let "; break;
502 case PROPERTY_MODE_SET: aCompleteProcName += "Set "; break;
503 case PROPERTY_MODE_NONE: OSL_FAIL( "Illegal PropertyMode PROPERTY_MODE_NONE" ); break;
505 aCompleteProcName += aName;
506 aName = aCompleteProcName;
512 SbiConstDef::SbiConstDef( const OUString& rName )
513 : SbiSymDef( rName )
515 nVal = 0; eType = SbxINTEGER;
518 void SbiConstDef::Set( double n, SbxDataType t )
520 aVal = ""; nVal = n; eType = t;
523 void SbiConstDef::Set( const OUString& n )
525 aVal = n; nVal = 0; eType = SbxSTRING;
528 SbiConstDef::~SbiConstDef()
531 SbiConstDef* SbiConstDef::GetConstDef()
533 return this;
536 SbiSymbols::~SbiSymbols()
538 for( const_iterator it = begin(); it != end(); ++it )
540 delete *it;
545 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */