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 76 : SbiStringPool::SbiStringPool( SbiParser* p )
39 : {
40 76 : pParser = p;
41 76 : }
42 :
43 76 : SbiStringPool::~SbiStringPool()
44 76 : {}
45 :
46 698 : const rtl::OUString& SbiStringPool::Find( sal_uInt32 n ) const
47 : {
48 698 : if( n == 0 || n > aData.size() )
49 0 : return aEmpty; //hack, returning a reference to a simulation of null
50 : else
51 698 : return aData[n - 1];
52 : }
53 :
54 878 : short SbiStringPool::Add( const OUString& rVal, bool bNoCase )
55 : {
56 878 : sal_uInt32 n = aData.size();
57 46706 : for( sal_uInt32 i = 0; i < n; ++i )
58 : {
59 46050 : OUString& p = aData[i];
60 91878 : if( ( bNoCase && p == rVal )
61 45828 : || ( !bNoCase && p.equalsIgnoreAsciiCase( rVal ) ) )
62 222 : return i+1;
63 : }
64 :
65 656 : aData.push_back(rVal);
66 656 : 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 360 : SbiSymPool::SbiSymPool( SbiStringPool& r, SbiSymScope s ) : rStrings( r )
90 : {
91 360 : pParser = r.GetParser();
92 360 : eScope = s;
93 360 : pParent = NULL;
94 : nCur =
95 360 : nProcId = 0;
96 360 : }
97 :
98 360 : SbiSymPool::~SbiSymPool()
99 360 : {}
100 :
101 :
102 38 : SbiSymDef* SbiSymPool::First()
103 : {
104 38 : nCur = (sal_uInt16) -1;
105 38 : return Next();
106 : }
107 :
108 280 : SbiSymDef* SbiSymPool::Next()
109 : {
110 280 : if( ++nCur >= aData.size() )
111 38 : return NULL;
112 : else
113 242 : return aData[ nCur ];
114 : }
115 :
116 :
117 170 : SbiSymDef* SbiSymPool::AddSym( const OUString& rName )
118 : {
119 170 : SbiSymDef* p = new SbiSymDef( rName );
120 170 : p->nPos = aData.size();
121 170 : p->nId = rStrings.Add( rName );
122 170 : p->nProcId = nProcId;
123 170 : p->pIn = this;
124 170 : aData.insert( aData.begin() + p->nPos, p );
125 170 : return p;
126 : }
127 :
128 36 : SbiProcDef* SbiSymPool::AddProc( const OUString& rName )
129 : {
130 36 : SbiProcDef* p = new SbiProcDef( pParser, rName );
131 36 : p->nPos = aData.size();
132 36 : p->nId = rStrings.Add( rName );
133 : // procs are always local
134 36 : p->nProcId = 0;
135 36 : p->pIn = this;
136 36 : aData.insert( aData.begin() + p->nPos, p );
137 36 : return p;
138 : }
139 :
140 : // adding an externally constructed symbol definition
141 :
142 258 : void SbiSymPool::Add( SbiSymDef* pDef )
143 : {
144 258 : if( pDef && pDef->pIn != this )
145 : {
146 258 : if( pDef->pIn )
147 : {
148 : #ifdef DBG_UTIL
149 :
150 : pParser->Error( SbERR_INTERNAL_ERROR, "Dbl Pool" );
151 : #endif
152 258 : return;
153 : }
154 :
155 258 : pDef->nPos = aData.size();
156 258 : if( !pDef->nId )
157 : {
158 : // A unique name must be created in the string pool
159 : // for static variables (Form ProcName:VarName)
160 258 : OUString aName( pDef->aName );
161 258 : if( pDef->IsStatic() )
162 : {
163 0 : aName = pParser->aGblStrings.Find( nProcId );
164 0 : aName += ":";
165 0 : aName += pDef->aName;
166 : }
167 258 : pDef->nId = rStrings.Add( aName );
168 : }
169 :
170 258 : if( !pDef->GetProcDef() )
171 : {
172 230 : pDef->nProcId = nProcId;
173 : }
174 258 : pDef->pIn = this;
175 258 : aData.insert( aData.begin() + pDef->nPos, pDef );
176 : }
177 : }
178 :
179 :
180 1962 : SbiSymDef* SbiSymPool::Find( const OUString& rName ) const
181 : {
182 1962 : sal_uInt16 nCount = aData.size();
183 5880 : for( sal_uInt16 i = 0; i < nCount; i++ )
184 : {
185 4712 : SbiSymDef* p = aData[ nCount - i - 1 ];
186 9424 : if( ( !p->nProcId || ( p->nProcId == nProcId)) &&
187 4712 : ( p->aName.equalsIgnoreAsciiCase(rName)))
188 : {
189 794 : return p;
190 : }
191 : }
192 1168 : if( pParent )
193 : {
194 998 : return pParent->Find( rName );
195 : }
196 : else
197 : {
198 170 : 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 148 : SbiSymDef* SbiSymPool::Get( sal_uInt16 n ) const
226 : {
227 148 : if( n >= aData.size() )
228 : {
229 0 : return NULL;
230 : }
231 : else
232 : {
233 148 : return aData[ n ];
234 : }
235 : }
236 :
237 4 : sal_uInt32 SbiSymPool::Define( const OUString& rName )
238 : {
239 4 : SbiSymDef* p = Find( rName );
240 4 : if( p )
241 : {
242 4 : if( p->IsDefined() )
243 : {
244 0 : pParser->Error( SbERR_LABEL_DEFINED, rName );
245 : }
246 : }
247 : else
248 : {
249 0 : p = AddSym( rName );
250 : }
251 4 : return p->Define();
252 : }
253 :
254 4 : sal_uInt32 SbiSymPool::Reference( const OUString& rName )
255 : {
256 4 : SbiSymDef* p = Find( rName );
257 4 : if( !p )
258 : {
259 4 : p = AddSym( rName );
260 : }
261 : // to be sure
262 4 : pParser->aGen.GenStmnt();
263 4 : return p->Reference();
264 : }
265 :
266 :
267 34 : void SbiSymPool::CheckRefs()
268 : {
269 38 : for( sal_uInt16 i = 0; i < aData.size(); i++ )
270 : {
271 4 : SbiSymDef* p = aData[ i ];
272 4 : if( !p->IsDefined() )
273 : {
274 0 : pParser->Error( SbERR_UNDEF_LABEL, p->GetName() );
275 : }
276 : }
277 34 : }
278 :
279 : /***************************************************************************
280 : |*
281 : |* symbol definitions
282 : |*
283 : ***************************************************************************/
284 :
285 470 : SbiSymDef::SbiSymDef( const OUString& rName ) : aName( rName )
286 : {
287 470 : eType = SbxEMPTY;
288 470 : nDims = 0;
289 470 : nTypeId = 0;
290 470 : nProcId = 0;
291 470 : nId = 0;
292 470 : nPos = 0;
293 470 : nLen = 0;
294 470 : nChain = 0;
295 : bAs =
296 : bNew =
297 : bStatic =
298 : bOpt =
299 : bParamArray =
300 : bWithEvents =
301 : bWithBrackets =
302 : bByVal =
303 : bChained =
304 470 : bGlobal = false;
305 : pIn =
306 470 : pPool = NULL;
307 470 : nDefaultId = 0;
308 470 : nFixedStringLength = -1;
309 470 : }
310 :
311 1160 : SbiSymDef::~SbiSymDef()
312 : {
313 470 : delete pPool;
314 690 : }
315 :
316 840 : SbiProcDef* SbiSymDef::GetProcDef()
317 : {
318 840 : return NULL;
319 : }
320 :
321 840 : SbiConstDef* SbiSymDef::GetConstDef()
322 : {
323 840 : return NULL;
324 : }
325 :
326 :
327 156 : const OUString& SbiSymDef::GetName()
328 : {
329 156 : if( pIn )
330 : {
331 46 : aName = pIn->rStrings.Find( nId );
332 : }
333 156 : return aName;
334 : }
335 :
336 :
337 626 : void SbiSymDef::SetType( SbxDataType t )
338 : {
339 626 : if( t == SbxVARIANT && pIn )
340 : {
341 172 : sal_Unicode cu = aName[0];
342 172 : if( cu < 256 )
343 : {
344 172 : char ch = (char)cu;
345 172 : if( ch == '_' )
346 : {
347 0 : ch = 'Z';
348 : }
349 172 : int ch2 = toupper( ch );
350 172 : unsigned char c = (unsigned char)ch2;
351 172 : if( c > 0 && c < 128 )
352 : {
353 172 : t = pIn->pParser->eDefTypes[ ch2 - 'A' ];
354 : }
355 : }
356 : }
357 626 : eType = t;
358 626 : }
359 :
360 : // construct a backchain, if not yet defined
361 : // the value that shall be stored as an operand is returned
362 :
363 4 : sal_uInt32 SbiSymDef::Reference()
364 : {
365 4 : if( !bChained )
366 : {
367 4 : sal_uInt32 n = nChain;
368 4 : nChain = pIn->pParser->aGen.GetOffset();
369 4 : return n;
370 : }
371 0 : else return nChain;
372 : }
373 :
374 :
375 38 : sal_uInt32 SbiSymDef::Define()
376 : {
377 38 : sal_uInt32 n = pIn->pParser->aGen.GetPC();
378 38 : pIn->pParser->aGen.GenStmnt();
379 38 : if( nChain )
380 : {
381 4 : pIn->pParser->aGen.BackChain( nChain );
382 : }
383 38 : nChain = n;
384 38 : bChained = true;
385 38 : 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 288 : SbiSymPool& SbiSymDef::GetPool()
392 : {
393 288 : if( !pPool )
394 : {
395 36 : pPool = new SbiSymPool( pIn->pParser->aGblStrings, SbLOCAL ); // is dumped
396 : }
397 288 : return *pPool;
398 : }
399 :
400 1544 : SbiSymScope SbiSymDef::GetScope() const
401 : {
402 1544 : 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 70 : 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 70 : , mbProcDecl( bProcDecl )
419 : {
420 70 : aParams.SetParent( &pParser->aPublics );
421 70 : pPool = new SbiSymPool( pParser->aGblStrings, SbLOCAL );
422 70 : pPool->SetParent( &aParams );
423 : nLine1 =
424 70 : nLine2 = 0;
425 70 : mePropMode = PROPERTY_MODE_NONE;
426 70 : bPublic = true;
427 70 : bCdecl = false;
428 70 : 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 70 : aParams.AddSym( aName );
432 70 : }
433 :
434 140 : SbiProcDef::~SbiProcDef()
435 140 : {}
436 :
437 260 : SbiProcDef* SbiProcDef::GetProcDef()
438 : {
439 260 : return this;
440 : }
441 :
442 112 : void SbiProcDef::SetType( SbxDataType t )
443 : {
444 112 : SbiSymDef::SetType( t );
445 112 : aParams.Get( 0 )->SetType( eType );
446 112 : }
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 6 : void SbiProcDef::Match( SbiProcDef* pOld )
453 : {
454 6 : SbiSymDef* po, *pn=NULL;
455 : // parameter 0 is the function name
456 : sal_uInt16 i;
457 18 : for( i = 1; i < aParams.GetSize(); i++ )
458 : {
459 12 : po = pOld->aParams.Get( i );
460 12 : pn = aParams.Get( i );
461 : // no type matching - that is done during running
462 : // but is it maybe called with too little parameters?
463 12 : if( !po && !pn->IsOptional() && !pn->IsParamArray() )
464 : {
465 0 : break;
466 : }
467 12 : po = pOld->aParams.Next();
468 : }
469 :
470 6 : 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 6 : if( !pIn && pOld->pIn )
477 : {
478 : // Replace old entry with the new one
479 6 : pOld->pIn->aData[ pOld->nPos ] = this;
480 6 : nPos = pOld->nPos;
481 6 : nId = pOld->nId;
482 6 : pIn = pOld->pIn;
483 : }
484 6 : delete pOld;
485 6 : }
486 :
487 34 : void SbiProcDef::setPropertyMode( PropertyMode ePropMode )
488 : {
489 34 : mePropMode = ePropMode;
490 34 : 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 34 : }
509 :
510 :
511 :
512 180 : SbiConstDef::SbiConstDef( const OUString& rName )
513 180 : : SbiSymDef( rName )
514 : {
515 180 : nVal = 0; eType = SbxINTEGER;
516 180 : }
517 :
518 0 : void SbiConstDef::Set( double n, SbxDataType t )
519 : {
520 0 : aVal = ""; nVal = n; eType = t;
521 0 : }
522 :
523 180 : void SbiConstDef::Set( const OUString& n )
524 : {
525 180 : aVal = n; nVal = 0; eType = SbxSTRING;
526 180 : }
527 :
528 360 : SbiConstDef::~SbiConstDef()
529 360 : {}
530 :
531 0 : SbiConstDef* SbiConstDef::GetConstDef()
532 : {
533 0 : return this;
534 : }
535 :
536 720 : SbiSymbols::~SbiSymbols()
537 : {
538 824 : for( const_iterator it = begin(); it != end(); ++it )
539 : {
540 464 : delete *it;
541 : }
542 360 : };
543 :
544 :
545 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|