1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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 /***************************************************************************
36 ***************************************************************************/
38 SbiStringPool::SbiStringPool( SbiParser
* 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
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
) ) )
65 aData
.push_back(rVal
);
69 short SbiStringPool::Add( double n
, SbxDataType 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;
80 return Add( rtl::OUString::createFromAscii( buf
) );
83 /***************************************************************************
87 ***************************************************************************/
89 SbiSymPool::SbiSymPool( SbiStringPool
& r
, SbiSymScope s
) : rStrings( r
)
91 pParser
= r
.GetParser();
98 SbiSymPool::~SbiSymPool()
102 SbiSymDef
* SbiSymPool::First()
104 nCur
= (sal_uInt16
) -1;
108 SbiSymDef
* SbiSymPool::Next()
110 if( ++nCur
>= aData
.size() )
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
;
124 aData
.insert( aData
.begin() + p
->nPos
, 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
136 aData
.insert( aData
.begin() + p
->nPos
, p
);
140 // adding an externally constructed symbol definition
142 void SbiSymPool::Add( SbiSymDef
* pDef
)
144 if( pDef
&& pDef
->pIn
!= this )
150 pParser
->Error( SbERR_INTERNAL_ERROR
, "Dbl Pool" );
155 pDef
->nPos
= aData
.size();
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
);
165 aName
+= pDef
->aName
;
167 pDef
->nId
= rStrings
.Add( aName
);
170 if( !pDef
->GetProcDef() )
172 pDef
->nProcId
= nProcId
;
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
)))
194 return pParent
->Find( rName
);
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
) ) )
215 return pParent
->FindId( n
);
223 // find via position (from 0)
225 SbiSymDef
* SbiSymPool::Get( sal_uInt16 n
) const
227 if( n
>= aData
.size() )
237 sal_uInt32
SbiSymPool::Define( const OUString
& rName
)
239 SbiSymDef
* p
= Find( rName
);
244 pParser
->Error( SbERR_LABEL_DEFINED
, rName
);
254 sal_uInt32
SbiSymPool::Reference( const OUString
& rName
)
256 SbiSymDef
* p
= Find( rName
);
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
)
308 nFixedStringLength
= -1;
311 SbiSymDef::~SbiSymDef()
316 SbiProcDef
* SbiSymDef::GetProcDef()
321 SbiConstDef
* SbiSymDef::GetConstDef()
327 const OUString
& SbiSymDef::GetName()
331 aName
= pIn
->rStrings
.Find( nId
);
337 void SbiSymDef::SetType( SbxDataType t
)
339 if( t
== SbxVARIANT
&& pIn
)
341 sal_Unicode cu
= aName
[0];
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' ];
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()
367 sal_uInt32 n
= nChain
;
368 nChain
= pIn
->pParser
->aGen
.GetOffset();
375 sal_uInt32
SbiSymDef::Define()
377 sal_uInt32 n
= pIn
->pParser
->aGen
.GetPC();
378 pIn
->pParser
->aGen
.GenStmnt();
381 pIn
->pParser
->aGen
.BackChain( 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()
395 pPool
= new SbiSymPool( pIn
->pParser
->aGblStrings
, SbLOCAL
); // is dumped
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
,
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
);
425 mePropMode
= PROPERTY_MODE_NONE
;
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()
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
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() )
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;
487 void SbiProcDef::setPropertyMode( PropertyMode ePropMode
)
489 mePropMode
= ePropMode
;
490 if( mePropMode
!= PROPERTY_MODE_NONE
)
492 // Prop name = original scanned procedure name
495 // CompleteProcName includes "Property xxx "
496 // to avoid conflicts with other symbols
497 OUString aCompleteProcName
= "Property ";
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
)
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()
536 SbiSymbols::~SbiSymbols()
538 for( const_iterator it
= begin(); it
!= end(); ++it
)
545 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */