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