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