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 "parser.hxx"
22 :
23 : #include <osl/diagnose.h>
24 :
25 : #include <stdio.h>
26 : #include <string.h>
27 : #include <ctype.h>
28 :
29 : // All symbol names are laid down int the symbol-pool's stringpool, so that
30 : // all symbols are handled in the same case. On saving the code-image, the
31 : // global stringpool with the respective symbols is also saved.
32 : // The local stringpool holds all the symbols that don't move to the image
33 : // (labels, constant names etc.).
34 :
35 : /***************************************************************************
36 : |*
37 : |* SbiStringPool
38 : |*
39 : ***************************************************************************/
40 :
41 370 : SbiStringPool::SbiStringPool( SbiParser* p )
42 : {
43 370 : pParser = p;
44 370 : }
45 :
46 370 : SbiStringPool::~SbiStringPool()
47 370 : {}
48 :
49 6697 : const OUString& SbiStringPool::Find( sal_uInt32 n ) const
50 : {
51 6697 : if( n == 0 || n > aData.size() )
52 0 : return aEmpty; //hack, returning a reference to a simulation of null
53 : else
54 6697 : return aData[n - 1];
55 : }
56 :
57 10058 : short SbiStringPool::Add( const OUString& rVal, bool bNoCase )
58 : {
59 10058 : sal_uInt32 n = aData.size();
60 854720 : for( sal_uInt32 i = 0; i < n; ++i )
61 : {
62 848635 : OUString& p = aData[i];
63 1697270 : if( ( bNoCase && p == rVal )
64 1693297 : || ( !bNoCase && p.equalsIgnoreAsciiCase( rVal ) ) )
65 3973 : return i+1;
66 : }
67 :
68 6085 : aData.push_back(rVal);
69 6085 : return (short) ++n;
70 : }
71 :
72 94 : short SbiStringPool::Add( double n, SbxDataType t )
73 : {
74 : char buf[ 40 ];
75 94 : switch( t )
76 : {
77 0 : case SbxINTEGER: snprintf( buf, sizeof(buf), "%d", (short) n ); break;
78 19 : case SbxLONG: snprintf( buf, sizeof(buf), "%ld", (long) n ); break;
79 0 : case SbxSINGLE: snprintf( buf, sizeof(buf), "%.6g", (float) n ); break;
80 75 : case SbxDOUBLE: snprintf( buf, sizeof(buf), "%.16g", n ); break;
81 0 : default: break;
82 : }
83 94 : return Add( OUString::createFromAscii( buf ) );
84 : }
85 :
86 : /***************************************************************************
87 : |*
88 : |* SbiSymPool
89 : |*
90 : ***************************************************************************/
91 :
92 4438 : SbiSymPool::SbiSymPool( SbiStringPool& r, SbiSymScope s ) : rStrings( r )
93 : {
94 4438 : pParser = r.GetParser();
95 4438 : eScope = s;
96 4438 : pParent = NULL;
97 : nCur =
98 4438 : nProcId = 0;
99 4438 : }
100 :
101 4438 : SbiSymPool::~SbiSymPool()
102 4438 : {}
103 :
104 :
105 185 : SbiSymDef* SbiSymPool::First()
106 : {
107 185 : nCur = (sal_uInt16) -1;
108 185 : return Next();
109 : }
110 :
111 2335 : SbiSymDef* SbiSymPool::Next()
112 : {
113 2335 : if( ++nCur >= aData.size() )
114 208 : return NULL;
115 : else
116 2127 : return &aData[ nCur ];
117 : }
118 :
119 :
120 2861 : SbiSymDef* SbiSymPool::AddSym( const OUString& rName )
121 : {
122 2861 : SbiSymDef* p = new SbiSymDef( rName );
123 2861 : p->nPos = aData.size();
124 2861 : p->nId = rStrings.Add( rName );
125 2861 : p->nProcId = nProcId;
126 2861 : p->pIn = this;
127 2861 : aData.insert( aData.begin() + p->nPos, p );
128 2861 : return p;
129 : }
130 :
131 746 : SbiProcDef* SbiSymPool::AddProc( const OUString& rName )
132 : {
133 746 : SbiProcDef* p = new SbiProcDef( pParser, rName );
134 746 : p->nPos = aData.size();
135 746 : p->nId = rStrings.Add( rName );
136 : // procs are always local
137 746 : p->nProcId = 0;
138 746 : p->pIn = this;
139 746 : aData.insert( aData.begin() + p->nPos, p );
140 746 : return p;
141 : }
142 :
143 : // adding an externally constructed symbol definition
144 :
145 2640 : void SbiSymPool::Add( SbiSymDef* pDef )
146 : {
147 2640 : if( pDef && pDef->pIn != this )
148 : {
149 2640 : if( pDef->pIn )
150 : {
151 : #ifdef DBG_UTIL
152 :
153 : pParser->Error( SbERR_INTERNAL_ERROR, "Dbl Pool" );
154 : #endif
155 2640 : return;
156 : }
157 :
158 2640 : pDef->nPos = aData.size();
159 2640 : if( !pDef->nId )
160 : {
161 : // A unique name must be created in the string pool
162 : // for static variables (Form ProcName:VarName)
163 2640 : OUString aName( pDef->aName );
164 2640 : if( pDef->IsStatic() )
165 : {
166 0 : aName = pParser->aGblStrings.Find( nProcId );
167 0 : aName += ":";
168 0 : aName += pDef->aName;
169 : }
170 2640 : pDef->nId = rStrings.Add( aName );
171 : }
172 :
173 2640 : if( !pDef->GetProcDef() )
174 : {
175 2438 : pDef->nProcId = nProcId;
176 : }
177 2640 : pDef->pIn = this;
178 2640 : aData.insert( aData.begin() + pDef->nPos, pDef );
179 : }
180 : }
181 :
182 :
183 32965 : SbiSymDef* SbiSymPool::Find( const OUString& rName )
184 : {
185 32965 : sal_uInt16 nCount = aData.size();
186 251622 : for( sal_uInt16 i = 0; i < nCount; i++ )
187 : {
188 229781 : SbiSymDef &r = aData[ nCount - i - 1 ];
189 459562 : if( ( !r.nProcId || ( r.nProcId == nProcId)) &&
190 229781 : ( r.aName.equalsIgnoreAsciiCase(rName)))
191 : {
192 11124 : return &r;
193 : }
194 : }
195 21841 : if( pParent )
196 : {
197 18829 : return pParent->Find( rName );
198 : }
199 : else
200 : {
201 3012 : return NULL;
202 : }
203 : }
204 :
205 :
206 : // find via position (from 0)
207 :
208 2447 : SbiSymDef* SbiSymPool::Get( sal_uInt16 n )
209 : {
210 2447 : if( n >= aData.size() )
211 : {
212 23 : return NULL;
213 : }
214 : else
215 : {
216 2424 : return &aData[ n ];
217 : }
218 : }
219 :
220 55 : sal_uInt32 SbiSymPool::Define( const OUString& rName )
221 : {
222 55 : SbiSymDef* p = Find( rName );
223 55 : if( p )
224 : {
225 55 : if( p->IsDefined() )
226 : {
227 0 : pParser->Error( SbERR_LABEL_DEFINED, rName );
228 : }
229 : }
230 : else
231 : {
232 0 : p = AddSym( rName );
233 : }
234 55 : return p->Define();
235 : }
236 :
237 55 : sal_uInt32 SbiSymPool::Reference( const OUString& rName )
238 : {
239 55 : SbiSymDef* p = Find( rName );
240 55 : if( !p )
241 : {
242 55 : p = AddSym( rName );
243 : }
244 : // to be sure
245 55 : pParser->aGen.GenStmnt();
246 55 : return p->Reference();
247 : }
248 :
249 :
250 415 : void SbiSymPool::CheckRefs()
251 : {
252 470 : for( size_t i = 0; i < aData.size(); i++ )
253 : {
254 55 : SbiSymDef &r = aData[ i ];
255 55 : if( !r.IsDefined() )
256 : {
257 0 : pParser->Error( SbERR_UNDEF_LABEL, r.GetName() );
258 : }
259 : }
260 415 : }
261 :
262 : /***************************************************************************
263 : |*
264 : |* symbol definitions
265 : |*
266 : ***************************************************************************/
267 :
268 6467 : SbiSymDef::SbiSymDef( const OUString& rName ) : aName( rName )
269 : {
270 6467 : eType = SbxEMPTY;
271 6467 : nDims = 0;
272 6467 : nTypeId = 0;
273 6467 : nProcId = 0;
274 6467 : nId = 0;
275 6467 : nPos = 0;
276 6467 : nLen = 0;
277 6467 : nChain = 0;
278 : bAs =
279 : bNew =
280 : bStatic =
281 : bOpt =
282 : bParamArray =
283 : bWithEvents =
284 : bWithBrackets =
285 : bByVal =
286 : bChained =
287 6467 : bGlobal = false;
288 : pIn =
289 6467 : pPool = NULL;
290 6467 : nDefaultId = 0;
291 6467 : nFixedStringLength = -1;
292 6467 : }
293 :
294 16782 : SbiSymDef::~SbiSymDef()
295 : {
296 6467 : delete pPool;
297 10315 : }
298 :
299 9935 : SbiProcDef* SbiSymDef::GetProcDef()
300 : {
301 9935 : return NULL;
302 : }
303 :
304 11317 : SbiConstDef* SbiSymDef::GetConstDef()
305 : {
306 11317 : return NULL;
307 : }
308 :
309 :
310 2830 : const OUString& SbiSymDef::GetName()
311 : {
312 2830 : if( pIn )
313 : {
314 640 : aName = pIn->rStrings.Find( nId );
315 : }
316 2830 : return aName;
317 : }
318 :
319 :
320 8867 : void SbiSymDef::SetType( SbxDataType t )
321 : {
322 8867 : if( t == SbxVARIANT && pIn )
323 : {
324 : //See if there have been any deftype statements to set the default type
325 : //of a variable based on its starting letter
326 2664 : sal_Unicode cu = aName[0];
327 2664 : if( cu < 256 )
328 : {
329 2664 : char ch = (char)cu;
330 2664 : if( ch == '_' )
331 : {
332 0 : ch = 'Z';
333 : }
334 2664 : int ch2 = toupper( ch );
335 2664 : int nIndex = ch2 - 'A';
336 2664 : if (nIndex >= 0 && nIndex < N_DEF_TYPES)
337 2661 : t = pIn->pParser->eDefTypes[nIndex];
338 : }
339 : }
340 8867 : eType = t;
341 8867 : }
342 :
343 : // construct a backchain, if not yet defined
344 : // the value that shall be stored as an operand is returned
345 :
346 55 : sal_uInt32 SbiSymDef::Reference()
347 : {
348 55 : if( !bChained )
349 : {
350 55 : sal_uInt32 n = nChain;
351 55 : nChain = pIn->pParser->aGen.GetOffset();
352 55 : return n;
353 : }
354 0 : else return nChain;
355 : }
356 :
357 :
358 474 : sal_uInt32 SbiSymDef::Define()
359 : {
360 474 : sal_uInt32 n = pIn->pParser->aGen.GetPC();
361 474 : pIn->pParser->aGen.GenStmnt();
362 474 : if( nChain )
363 : {
364 55 : pIn->pParser->aGen.BackChain( nChain );
365 : }
366 474 : nChain = n;
367 474 : bChained = true;
368 474 : 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 3778 : SbiSymPool& SbiSymDef::GetPool()
375 : {
376 3778 : if( !pPool )
377 : {
378 388 : pPool = new SbiSymPool( pIn->pParser->aGblStrings, SbLOCAL ); // is dumped
379 : }
380 3778 : return *pPool;
381 : }
382 :
383 22584 : SbiSymScope SbiSymDef::GetScope() const
384 : {
385 22584 : 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 1165 : 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 1165 : , mbProcDecl( bProcDecl )
402 : {
403 1165 : aParams.SetParent( &pParser->aPublics );
404 1165 : pPool = new SbiSymPool( pParser->aGblStrings, SbLOCAL );
405 1165 : pPool->SetParent( &aParams );
406 : nLine1 =
407 1165 : nLine2 = 0;
408 1165 : mePropMode = PropertyMode::NONE;
409 1165 : bPublic = true;
410 1165 : bCdecl = false;
411 1165 : 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 1165 : aParams.AddSym( aName );
415 1165 : }
416 :
417 2330 : SbiProcDef::~SbiProcDef()
418 2330 : {}
419 :
420 2984 : SbiProcDef* SbiProcDef::GetProcDef()
421 : {
422 2984 : return this;
423 : }
424 :
425 1881 : void SbiProcDef::SetType( SbxDataType t )
426 : {
427 1881 : SbiSymDef::SetType( t );
428 1881 : aParams.Get( 0 )->SetType( eType );
429 1881 : }
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 217 : void SbiProcDef::Match( SbiProcDef* pOld )
436 : {
437 217 : SbiSymDef *pn=NULL;
438 : // parameter 0 is the function name
439 : sal_uInt16 i;
440 388 : for( i = 1; i < aParams.GetSize(); i++ )
441 : {
442 171 : SbiSymDef* po = pOld->aParams.Get( i );
443 171 : pn = aParams.Get( i );
444 : // no type matching - that is done during running
445 : // but is it maybe called with too little parameters?
446 171 : if( !po && !pn->IsOptional() && !pn->IsParamArray() )
447 : {
448 0 : break;
449 : }
450 171 : pOld->aParams.Next();
451 : }
452 :
453 217 : 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 217 : if( !pIn && pOld->pIn )
460 : {
461 : // Replace old entry with the new one
462 217 : nPos = pOld->nPos;
463 217 : nId = pOld->nId;
464 217 : pIn = pOld->pIn;
465 217 : pIn->aData.replace( nPos, this ).release();
466 : }
467 217 : delete pOld;
468 217 : }
469 :
470 415 : void SbiProcDef::setPropertyMode( PropertyMode ePropMode )
471 : {
472 415 : mePropMode = ePropMode;
473 415 : if( mePropMode != PropertyMode::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 PropertyMode::Get: aCompleteProcName += "Get "; break;
484 0 : case PropertyMode::Let: aCompleteProcName += "Let "; break;
485 0 : case PropertyMode::Set: aCompleteProcName += "Set "; break;
486 0 : case PropertyMode::NONE: OSL_FAIL( "Illegal PropertyMode PropertyMode::NONE" ); break;
487 : }
488 0 : aCompleteProcName += aName;
489 0 : aName = aCompleteProcName;
490 : }
491 415 : }
492 :
493 :
494 :
495 1454 : SbiConstDef::SbiConstDef( const OUString& rName )
496 1454 : : SbiSymDef( rName )
497 : {
498 1454 : nVal = 0; eType = SbxINTEGER;
499 1454 : }
500 :
501 60 : void SbiConstDef::Set( double n, SbxDataType t )
502 : {
503 60 : aVal.clear(); nVal = n; eType = t;
504 60 : }
505 :
506 1394 : void SbiConstDef::Set( const OUString& n )
507 : {
508 1394 : aVal = n; nVal = 0; eType = SbxSTRING;
509 1394 : }
510 :
511 2908 : SbiConstDef::~SbiConstDef()
512 2908 : {}
513 :
514 383 : SbiConstDef* SbiConstDef::GetConstDef()
515 : {
516 383 : return this;
517 : }
518 :
519 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|