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