bump product version to 5.0.4.1
[LibreOffice.git] / basic / source / comp / symtbl.cxx
blobb30173fb48ff29da40629c9898e382f8a261d599
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 "parser.hxx"
23 #include <osl/diagnose.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <ctype.h>
29 // All symbol names are laid down int the symbol-pool's stringpool, so that
30 // all symbols are handled in the same case. On saving the code-image, the
31 // global stringpool with the respective symbols is also saved.
32 // The local stringpool holds all the symbols that don't move to the image
33 // (labels, constant names etc.).
35 /***************************************************************************
37 |* SbiStringPool
39 ***************************************************************************/
41 SbiStringPool::SbiStringPool( SbiParser* p )
43 pParser = p;
46 SbiStringPool::~SbiStringPool()
49 const OUString& SbiStringPool::Find( sal_uInt32 n ) const
51 if( n == 0 || n > aData.size() )
52 return aEmpty; //hack, returning a reference to a simulation of null
53 else
54 return aData[n - 1];
57 short SbiStringPool::Add( const OUString& rVal, bool bNoCase )
59 sal_uInt32 n = aData.size();
60 for( sal_uInt32 i = 0; i < n; ++i )
62 OUString& p = aData[i];
63 if( ( bNoCase && p == rVal )
64 || ( !bNoCase && p.equalsIgnoreAsciiCase( rVal ) ) )
65 return i+1;
68 aData.push_back(rVal);
69 return (short) ++n;
72 short SbiStringPool::Add( double n, SbxDataType t )
74 char buf[ 40 ];
75 switch( t )
77 case SbxINTEGER: snprintf( buf, sizeof(buf), "%d", (short) n ); break;
78 case SbxLONG: snprintf( buf, sizeof(buf), "%ld", (long) n ); break;
79 case SbxSINGLE: snprintf( buf, sizeof(buf), "%.6g", (float) n ); break;
80 case SbxDOUBLE: snprintf( buf, sizeof(buf), "%.16g", n ); break;
81 default: break;
83 return Add( OUString::createFromAscii( buf ) );
86 /***************************************************************************
88 |* SbiSymPool
90 ***************************************************************************/
92 SbiSymPool::SbiSymPool( SbiStringPool& r, SbiSymScope s ) : rStrings( r )
94 pParser = r.GetParser();
95 eScope = s;
96 pParent = NULL;
97 nCur =
98 nProcId = 0;
101 SbiSymPool::~SbiSymPool()
105 SbiSymDef* SbiSymPool::First()
107 nCur = (sal_uInt16) -1;
108 return Next();
111 SbiSymDef* SbiSymPool::Next()
113 if( ++nCur >= aData.size() )
114 return NULL;
115 else
116 return &aData[ nCur ];
120 SbiSymDef* SbiSymPool::AddSym( const OUString& rName )
122 SbiSymDef* p = new SbiSymDef( rName );
123 p->nPos = aData.size();
124 p->nId = rStrings.Add( rName );
125 p->nProcId = nProcId;
126 p->pIn = this;
127 aData.insert( aData.begin() + p->nPos, p );
128 return p;
131 SbiProcDef* SbiSymPool::AddProc( const OUString& rName )
133 SbiProcDef* p = new SbiProcDef( pParser, rName );
134 p->nPos = aData.size();
135 p->nId = rStrings.Add( rName );
136 // procs are always local
137 p->nProcId = 0;
138 p->pIn = this;
139 aData.insert( aData.begin() + p->nPos, p );
140 return p;
143 // adding an externally constructed symbol definition
145 void SbiSymPool::Add( SbiSymDef* pDef )
147 if( pDef && pDef->pIn != this )
149 if( pDef->pIn )
151 #ifdef DBG_UTIL
153 pParser->Error( SbERR_INTERNAL_ERROR, "Dbl Pool" );
154 #endif
155 return;
158 pDef->nPos = aData.size();
159 if( !pDef->nId )
161 // A unique name must be created in the string pool
162 // for static variables (Form ProcName:VarName)
163 OUString aName( pDef->aName );
164 if( pDef->IsStatic() )
166 aName = pParser->aGblStrings.Find( nProcId );
167 aName += ":";
168 aName += pDef->aName;
170 pDef->nId = rStrings.Add( aName );
173 if( !pDef->GetProcDef() )
175 pDef->nProcId = nProcId;
177 pDef->pIn = this;
178 aData.insert( aData.begin() + pDef->nPos, pDef );
183 SbiSymDef* SbiSymPool::Find( const OUString& rName )
185 sal_uInt16 nCount = aData.size();
186 for( sal_uInt16 i = 0; i < nCount; i++ )
188 SbiSymDef &r = aData[ nCount - i - 1 ];
189 if( ( !r.nProcId || ( r.nProcId == nProcId)) &&
190 ( r.aName.equalsIgnoreAsciiCase(rName)))
192 return &r;
195 if( pParent )
197 return pParent->Find( rName );
199 else
201 return NULL;
206 // find via position (from 0)
208 SbiSymDef* SbiSymPool::Get( sal_uInt16 n )
210 if( n >= aData.size() )
212 return NULL;
214 else
216 return &aData[ n ];
220 sal_uInt32 SbiSymPool::Define( const OUString& rName )
222 SbiSymDef* p = Find( rName );
223 if( p )
225 if( p->IsDefined() )
227 pParser->Error( SbERR_LABEL_DEFINED, rName );
230 else
232 p = AddSym( rName );
234 return p->Define();
237 sal_uInt32 SbiSymPool::Reference( const OUString& rName )
239 SbiSymDef* p = Find( rName );
240 if( !p )
242 p = AddSym( rName );
244 // to be sure
245 pParser->aGen.GenStmnt();
246 return p->Reference();
250 void SbiSymPool::CheckRefs()
252 for( sal_uInt16 i = 0; i < aData.size(); i++ )
254 SbiSymDef &r = aData[ i ];
255 if( !r.IsDefined() )
257 pParser->Error( SbERR_UNDEF_LABEL, r.GetName() );
262 /***************************************************************************
264 |* symbol definitions
266 ***************************************************************************/
268 SbiSymDef::SbiSymDef( const OUString& rName ) : aName( rName )
270 eType = SbxEMPTY;
271 nDims = 0;
272 nTypeId = 0;
273 nProcId = 0;
274 nId = 0;
275 nPos = 0;
276 nLen = 0;
277 nChain = 0;
278 bAs =
279 bNew =
280 bStatic =
281 bOpt =
282 bParamArray =
283 bWithEvents =
284 bWithBrackets =
285 bByVal =
286 bChained =
287 bGlobal = false;
288 pIn =
289 pPool = NULL;
290 nDefaultId = 0;
291 nFixedStringLength = -1;
294 SbiSymDef::~SbiSymDef()
296 delete pPool;
299 SbiProcDef* SbiSymDef::GetProcDef()
301 return NULL;
304 SbiConstDef* SbiSymDef::GetConstDef()
306 return NULL;
310 const OUString& SbiSymDef::GetName()
312 if( pIn )
314 aName = pIn->rStrings.Find( nId );
316 return aName;
320 void SbiSymDef::SetType( SbxDataType t )
322 if( t == SbxVARIANT && pIn )
324 //See if there have been any deftype statements to set the default type
325 //of a variable based on its starting letter
326 sal_Unicode cu = aName[0];
327 if( cu < 256 )
329 char ch = (char)cu;
330 if( ch == '_' )
332 ch = 'Z';
334 int ch2 = toupper( ch );
335 int nIndex = ch2 - 'A';
336 if (nIndex >= 0 && nIndex < N_DEF_TYPES)
337 t = pIn->pParser->eDefTypes[nIndex];
340 eType = t;
343 // construct a backchain, if not yet defined
344 // the value that shall be stored as an operand is returned
346 sal_uInt32 SbiSymDef::Reference()
348 if( !bChained )
350 sal_uInt32 n = nChain;
351 nChain = pIn->pParser->aGen.GetOffset();
352 return n;
354 else return nChain;
358 sal_uInt32 SbiSymDef::Define()
360 sal_uInt32 n = pIn->pParser->aGen.GetPC();
361 pIn->pParser->aGen.GenStmnt();
362 if( nChain )
364 pIn->pParser->aGen.BackChain( nChain );
366 nChain = n;
367 bChained = true;
368 return nChain;
371 // A symbol definition may have its own pool. This is the case
372 // for objects and procedures (local variable)
374 SbiSymPool& SbiSymDef::GetPool()
376 if( !pPool )
378 pPool = new SbiSymPool( pIn->pParser->aGblStrings, SbLOCAL ); // is dumped
380 return *pPool;
383 SbiSymScope SbiSymDef::GetScope() const
385 return pIn ? pIn->GetScope() : SbLOCAL;
389 // The procedure definition has three pools:
390 // 1) aParams: is filled by the definition. Contains the
391 // parameters' names, like they're used inside the body.
392 // The first element is the return value.
393 // 2) pPool: all local variables
394 // 3) aLabels: labels
396 SbiProcDef::SbiProcDef( SbiParser* pParser, const OUString& rName,
397 bool bProcDecl )
398 : SbiSymDef( rName )
399 , aParams( pParser->aGblStrings, SbPARAM ) // is dumped
400 , aLabels( pParser->aLclStrings, SbLOCAL ) // is not dumped
401 , mbProcDecl( bProcDecl )
403 aParams.SetParent( &pParser->aPublics );
404 pPool = new SbiSymPool( pParser->aGblStrings, SbLOCAL );
405 pPool->SetParent( &aParams );
406 nLine1 =
407 nLine2 = 0;
408 mePropMode = PROPERTY_MODE_NONE;
409 bPublic = true;
410 bCdecl = false;
411 bStatic = false;
412 // For return values the first element of the parameter
413 // list is always defined with name and type of the proc
414 aParams.AddSym( aName );
417 SbiProcDef::~SbiProcDef()
420 SbiProcDef* SbiProcDef::GetProcDef()
422 return this;
425 void SbiProcDef::SetType( SbxDataType t )
427 SbiSymDef::SetType( t );
428 aParams.Get( 0 )->SetType( eType );
431 // match with a forward-declaration
432 // if the match is OK, pOld is replaced by this in the pool
433 // pOld is deleted in any case!
435 void SbiProcDef::Match( SbiProcDef* pOld )
437 SbiSymDef *pn=NULL;
438 // parameter 0 is the function name
439 sal_uInt16 i;
440 for( i = 1; i < aParams.GetSize(); i++ )
442 SbiSymDef* po = pOld->aParams.Get( i );
443 pn = aParams.Get( i );
444 // no type matching - that is done during running
445 // but is it maybe called with too little parameters?
446 if( !po && !pn->IsOptional() && !pn->IsParamArray() )
448 break;
450 pOld->aParams.Next();
453 if( pn && i < aParams.GetSize() && pOld->pIn )
455 // mark the whole line
456 pOld->pIn->GetParser()->SetCol1( 0 );
457 pOld->pIn->GetParser()->Error( SbERR_BAD_DECLARATION, aName );
459 if( !pIn && pOld->pIn )
461 // Replace old entry with the new one
462 nPos = pOld->nPos;
463 nId = pOld->nId;
464 pIn = pOld->pIn;
465 pIn->aData.replace( nPos, this ).release();
467 delete pOld;
470 void SbiProcDef::setPropertyMode( PropertyMode ePropMode )
472 mePropMode = ePropMode;
473 if( mePropMode != PROPERTY_MODE_NONE )
475 // Prop name = original scanned procedure name
476 maPropName = aName;
478 // CompleteProcName includes "Property xxx "
479 // to avoid conflicts with other symbols
480 OUString aCompleteProcName = "Property ";
481 switch( mePropMode )
483 case PROPERTY_MODE_GET: aCompleteProcName += "Get "; break;
484 case PROPERTY_MODE_LET: aCompleteProcName += "Let "; break;
485 case PROPERTY_MODE_SET: aCompleteProcName += "Set "; break;
486 case PROPERTY_MODE_NONE: OSL_FAIL( "Illegal PropertyMode PROPERTY_MODE_NONE" ); break;
488 aCompleteProcName += aName;
489 aName = aCompleteProcName;
495 SbiConstDef::SbiConstDef( const OUString& rName )
496 : SbiSymDef( rName )
498 nVal = 0; eType = SbxINTEGER;
501 void SbiConstDef::Set( double n, SbxDataType t )
503 aVal.clear(); nVal = n; eType = t;
506 void SbiConstDef::Set( const OUString& n )
508 aVal = n; nVal = 0; eType = SbxSTRING;
511 SbiConstDef::~SbiConstDef()
514 SbiConstDef* SbiConstDef::GetConstDef()
516 return this;
519 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */