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