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 .
23 #include <osl/diagnose.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 /***************************************************************************
39 ***************************************************************************/
41 SbiStringPool::SbiStringPool( SbiParser
* 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
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
) ) )
68 aData
.push_back(rVal
);
72 short SbiStringPool::Add( double n
, SbxDataType 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;
83 return Add( OUString::createFromAscii( buf
) );
86 /***************************************************************************
90 ***************************************************************************/
92 SbiSymPool::SbiSymPool( SbiStringPool
& r
, SbiSymScope s
) : rStrings( r
)
94 pParser
= r
.GetParser();
101 SbiSymPool::~SbiSymPool()
105 SbiSymDef
* SbiSymPool::First()
107 nCur
= (sal_uInt16
) -1;
111 SbiSymDef
* SbiSymPool::Next()
113 if( ++nCur
>= aData
.size() )
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
;
127 aData
.insert( aData
.begin() + p
->nPos
, 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
139 aData
.insert( aData
.begin() + p
->nPos
, p
);
143 // adding an externally constructed symbol definition
145 void SbiSymPool::Add( SbiSymDef
* pDef
)
147 if( pDef
&& pDef
->pIn
!= this )
153 pParser
->Error( SbERR_INTERNAL_ERROR
, "Dbl Pool" );
158 pDef
->nPos
= aData
.size();
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
);
168 aName
+= pDef
->aName
;
170 pDef
->nId
= rStrings
.Add( aName
);
173 if( !pDef
->GetProcDef() )
175 pDef
->nProcId
= nProcId
;
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
)))
197 return pParent
->Find( rName
);
206 // find via position (from 0)
208 SbiSymDef
* SbiSymPool::Get( sal_uInt16 n
)
210 if( n
>= aData
.size() )
220 sal_uInt32
SbiSymPool::Define( const OUString
& rName
)
222 SbiSymDef
* p
= Find( rName
);
227 pParser
->Error( SbERR_LABEL_DEFINED
, rName
);
237 sal_uInt32
SbiSymPool::Reference( const OUString
& rName
)
239 SbiSymDef
* p
= Find( rName
);
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
];
257 pParser
->Error( SbERR_UNDEF_LABEL
, r
.GetName() );
262 /***************************************************************************
264 |* symbol definitions
266 ***************************************************************************/
268 SbiSymDef::SbiSymDef( const OUString
& rName
) : aName( rName
)
291 nFixedStringLength
= -1;
294 SbiSymDef::~SbiSymDef()
299 SbiProcDef
* SbiSymDef::GetProcDef()
304 SbiConstDef
* SbiSymDef::GetConstDef()
310 const OUString
& SbiSymDef::GetName()
314 aName
= pIn
->rStrings
.Find( nId
);
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];
334 int ch2
= toupper( ch
);
335 int nIndex
= ch2
- 'A';
336 if (nIndex
>= 0 && nIndex
< N_DEF_TYPES
)
337 t
= pIn
->pParser
->eDefTypes
[nIndex
];
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()
350 sal_uInt32 n
= nChain
;
351 nChain
= pIn
->pParser
->aGen
.GetOffset();
358 sal_uInt32
SbiSymDef::Define()
360 sal_uInt32 n
= pIn
->pParser
->aGen
.GetPC();
361 pIn
->pParser
->aGen
.GenStmnt();
364 pIn
->pParser
->aGen
.BackChain( 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()
378 pPool
= new SbiSymPool( pIn
->pParser
->aGblStrings
, SbLOCAL
); // is dumped
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
,
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
);
408 mePropMode
= PROPERTY_MODE_NONE
;
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()
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
)
438 // parameter 0 is the function name
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() )
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
465 pIn
->aData
.replace( nPos
, this ).release();
470 void SbiProcDef::setPropertyMode( PropertyMode ePropMode
)
472 mePropMode
= ePropMode
;
473 if( mePropMode
!= PROPERTY_MODE_NONE
)
475 // Prop name = original scanned procedure name
478 // CompleteProcName includes "Property xxx "
479 // to avoid conflicts with other symbols
480 OUString aCompleteProcName
= "Property ";
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
)
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()
519 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */