Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  symtbl.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */



#include <memory>
#include <parser.hxx>

#include <osl/diagnose.h>

#include <stdio.h>
#include <rtl/character.hxx>
#include <basic/sberrors.hxx>
#include <utility>

// All symbol names are laid down int the symbol-pool's stringpool, so that
// all symbols are handled in the same case. On saving the code-image, the
// global stringpool with the respective symbols is also saved.
// The local stringpool holds all the symbols that don't move to the image
// (labels, constant names etc.).

SbiStringPool::SbiStringPool( )
{}

SbiStringPool::~SbiStringPool()
{}

const OUString & SbiStringPool::Find( sal_uInt32 n ) const
{
    if( n == 0 || n > aData.size() )
        return EMPTY_OUSTRING;
    else
        return aData[n - 1];
}

short SbiStringPool::Add( const OUString& rVal )
{
    sal_uInt32 n = aData.size();
    for( sal_uInt32 i = 0; i < n; ++i )
    {
        OUString& p = aData[i];
        if( p == rVal )
            return i+1;
    }

    aData.push_back(rVal);
    return static_cast<short>(++n);
}

short SbiStringPool::Add(double n, SbxDataType t)
{
    size_t size = 0;
    const size_t aBufLength = 40;
    char buf[aBufLength]{};

    // tdf#143707 - add the type character after the null termination of the string in order to
    // keep compatibility. After the type character has been added, the buffer contains the value
    // of the double n, the string termination symbol, and the type character.
    switch( t )
    {
        // tdf#142460 - properly handle boolean values in string pool
        case SbxBOOL:
            size = snprintf(buf, sizeof(buf), "%d"static_cast<short>(n)) + 1;
            buf[size++] = 'b';
            break;
        // tdf#131296 - store numeric value including its type character
        // See GetSuffixType in basic/source/comp/scanner.cxx for type characters
        case SbxINTEGER:
            size = snprintf(buf, sizeof(buf), "%d"static_cast<short>(n)) + 1;
            buf[size++] = '%';
            break;
        case SbxLONG:
            size = snprintf(buf, sizeof(buf), "%" SAL_PRIdINT32, static_cast<sal_Int32>(n)) + 1;
            buf[size++] = '&';
            break;
        case SbxSINGLE:
            size = snprintf(buf, sizeof(buf), "%.6g"static_cast<float>(n)) + 1;
            buf[size++] = '!';
            break;
        case SbxDOUBLE:
            size = snprintf(buf, sizeof(buf), "%.16g", n) + 1;
            buf[size++] = '#';
            break;
        case SbxCURRENCY:
            size = snprintf(buf, sizeof(buf), "%.16g", n) + 1;
            buf[size++] = '@';
            break;
        case SbxDATE:
            // tdf#168569 - support date values in string pool
            size = snprintf(buf, sizeof(buf), "%.16g", n) + 1;
            buf[size++] = 'd'// Not in GetSuffixType
            break;
        default: assert(false); break// should not happen
    }

    // tdf#143707 - add the content of the buffer to the string pool including its calculated length
    return Add(OUString::fromUtf8(std::string_view(buf, size)));
}

SbiSymPool::SbiSymPool( SbiStringPool& r, SbiSymScope s, SbiParser* pP ) :
    rStrings(r),
    pParent(nullptr),
    pParser(pP),
    eScope(s),
    nProcId(0),
    nCur(0)
{
}

SbiSymPool::~SbiSymPool()
{}


SbiSymDef* SbiSymPool::First()
{
    nCur = sal_uInt16(-1);
    return Next();
}

SbiSymDef* SbiSymPool::Next()
{
    if (m_Data.size() <= ++nCur)
        return nullptr;
    else
        return m_Data[ nCur ].get();
}


SbiSymDef* SbiSymPool::AddSym( const OUString& rName )
{
    SbiSymDef* p = new SbiSymDef( rName );
    p->nPos    = m_Data.size();
    p->nId     = rStrings.Add( rName );
    p->nProcId = nProcId;
    p->pIn     = this;
    m_Data.insert( m_Data.begin() + p->nPos, std::unique_ptr<SbiSymDef>(p) );
    return p;
}

SbiProcDef* SbiSymPool::AddProc( const OUString& rName )
{
    SbiProcDef* p = new SbiProcDef( pParser, rName );
    p->nPos    = m_Data.size();
    p->nId     = rStrings.Add( rName );
    // procs are always local
    p->nProcId = 0;
    p->pIn     = this;
    m_Data.insert( m_Data.begin() + p->nPos, std::unique_ptr<SbiProcDef>(p) );
    return p;
}

// adding an externally constructed symbol definition

void SbiSymPool::Add( SbiSymDef* pDef )
{
    if( !(pDef && pDef->pIn != this) )
        return;

    if( pDef->pIn )
    {
#ifdef DBG_UTIL

        pParser->Error( ERRCODE_BASIC_INTERNAL_ERROR, u"Dbl Pool"_ustr );
#endif
        return;
    }

    pDef->nPos = m_Data.size();
    if( !pDef->nId )
    {
        // A unique name must be created in the string pool
        // for static variables (Form ProcName:VarName)
        OUString aName( pDef->aName );
        if( pDef->IsStatic() )
        {
            aName = pParser->aGblStrings.Find( nProcId )
                  + ":"
                  + pDef->aName;
        }
        pDef->nId = rStrings.Add( aName );
    }

    if( !pDef->GetProcDef() )
    {
        pDef->nProcId = nProcId;
    }
    pDef->pIn = this;
    m_Data.insert( m_Data.begin() + pDef->nPos, std::unique_ptr<SbiSymDef>(pDef) );
}


SbiSymDef* SbiSymPool::Find( const OUString& rName, bool bSearchInParents )
{
    sal_uInt16 nCount = m_Data.size();
    for( sal_uInt16 i = 0; i < nCount; i++ )
    {
        SbiSymDef &r = *m_Data[ nCount - i - 1 ];
        if( ( !r.nProcId || ( r.nProcId == nProcId)) &&
            ( r.aName.equalsIgnoreAsciiCase(rName)))
        {
            return &r;
        }
    }
    if( bSearchInParents && pParent )
    {
        return pParent->Find( rName );
    }
    else
    {
        return nullptr;
    }
}


// find via position (from 0)

SbiSymDef* SbiSymPool::Get( sal_uInt16 n )
{
    if (m_Data.size() <= n)
    {
        return nullptr;
    }
    else
    {
        return m_Data[ n ].get();
    }
}

sal_uInt32 SbiSymPool::Define( const OUString& rName )
{
    SbiSymDef* p = Find( rName );
    if( p )
    {
        if( p->IsDefined() )
        {
            pParser->Error( ERRCODE_BASIC_LABEL_DEFINED, rName );
        }
    }
    else
    {
        p = AddSym( rName );
    }
    return p->Define();
}

sal_uInt32 SbiSymPool::Reference( const OUString& rName )
{
    SbiSymDef* p = Find( rName );
    if( !p )
    {
        p = AddSym( rName );
    }
    // to be sure
    pParser->aGen.GenStmnt();
    return p->Reference();
}


void SbiSymPool::CheckRefs()
{
    for (std::unique_ptr<SbiSymDef> & r : m_Data)
    {
        if( !r->IsDefined() )
        {
            pParser->Error( ERRCODE_BASIC_UNDEF_LABEL, r->GetName() );
        }
    }
}

SbiSymDef::SbiSymDef( OUString _aName ) :
    aName(std::move(_aName)),
    eType(SbxEMPTY),
    pIn(nullptr),
    nLen(0),
    nDims(0),
    nId(0),
    nTypeId(0),
    nProcId(0),
    nPos(0),
    nChain(0),
    bNew(false),
    bChained(false),
    bByVal(false),
    bOpt(false),
    bStatic(false),
    bAs(false),
    bGlobal(false),
    bParamArray(false),
    bWithEvents(false),
    bWithBrackets(false),
    nDefaultId(0),
    nFixedStringLength(-1)
{
}

SbiSymDef::~SbiSymDef()
{
}

SbiProcDef* SbiSymDef::GetProcDef()
{
    return nullptr;
}

SbiConstDef* SbiSymDef::GetConstDef()
{
    return nullptr;
}


const OUString& SbiSymDef::GetName()
{
    if( pIn )
    {
        aName = pIn->rStrings.Find( nId );
    }
    return aName;
}


void SbiSymDef::SetType( SbxDataType t )
{
    if( t == SbxVARIANT && pIn )
    {
        //See if there have been any deftype statements to set the default type
        //of a variable based on its starting letter
        sal_Unicode cu = aName[0];
        if( cu < 256 )
        {
            unsigned char ch = static_cast<unsigned char>(cu);
            if( ch == '_' )
            {
                ch = 'Z';
            }
            int ch2 = rtl::toAsciiUpperCase( ch );
            int nIndex = ch2 - 'A';
            if (nIndex >= 0 && nIndex < N_DEF_TYPES)
                t = pIn->pParser->eDefTypes[nIndex];
        }
    }
    eType = t;
}

// construct a backchain, if not yet defined
// the value that shall be stored as an operand is returned

sal_uInt32 SbiSymDef::Reference()
{
    if( !bChained )
    {
        sal_uInt32 n = nChain;
        nChain = pIn->pParser->aGen.GetOffset();
        return n;
    }
    else return nChain;
}


sal_uInt32 SbiSymDef::Define()
{
    sal_uInt32 n = pIn->pParser->aGen.GetPC();
    pIn->pParser->aGen.GenStmnt();
    if( nChain )
    {
        pIn->pParser->aGen.BackChain( nChain );
    }
    nChain = n;
    bChained = true;
    return nChain;
}

// A symbol definition may have its own pool. This is the case
// for objects and procedures (local variable)

SbiSymPool& SbiSymDef::GetPool()
{
    if( !pPool )
    {
        pPool = std::make_unique<SbiSymPool>( pIn->pParser->aGblStrings, SbLOCAL, pIn->pParser );// is dumped
    }
    return *pPool;
}

SbiSymScope SbiSymDef::GetScope() const
{
    return pIn ? pIn->GetScope() : SbLOCAL;
}


// The procedure definition has three pools:
// 1) aParams: is filled by the definition. Contains the
//    parameters' names, like they're used inside the body.
//    The first element is the return value.
// 2) pPool: all local variables
// 3) aLabels: labels

SbiProcDef::SbiProcDef( SbiParser* pParser, const OUString& rName,
                        bool bProcDecl )
         : SbiSymDef( rName )
         , aParams( pParser->aGblStrings, SbPARAM, pParser )  // is dumped
         , aLabels( pParser->aLclStrings, SbLOCAL, pParser )  // is not dumped
         , mbProcDecl( bProcDecl )
{
    aParams.SetParent( &pParser->aPublics );
    pPool = std::make_unique<SbiSymPool>( pParser->aGblStrings, SbLOCAL, pParser );
    pPool->SetParent( &aParams );
    nLine1  =
    nLine2  = 0;
    mePropMode = PropertyMode::NONE;
    bPublic = true;
    bCdecl  = false;
    bStatic = false;
    // For return values the first element of the parameter
    // list is always defined with name and type of the proc
    aParams.AddSym( aName );
}

SbiProcDef::~SbiProcDef()
{}

SbiProcDef* SbiProcDef::GetProcDef()
{
    return this;
}

void SbiProcDef::SetType( SbxDataType t )
{
    SbiSymDef::SetType( t );
    aParams.Get( 0 )->SetType( eType );
}

// match with a forward-declaration
// if the match is OK, pOld is replaced by this in the pool
// pOld is deleted in any case!

void SbiProcDef::Match( SbiProcDef* pOld )
{
    SbiSymDef *pn=nullptr;
    // parameter 0 is the function name
    sal_uInt16 i;
    for( i = 1; i < aParams.GetSize(); i++ )
    {
        SbiSymDef* po = pOld->aParams.Get( i );
        pn = aParams.Get( i );
        // no type matching - that is done during running
        // but is it maybe called with too little parameters?
        if( !po && !pn->IsOptional() && !pn->IsParamArray() )
        {
            break;
        }
        pOld->aParams.Next();
    }

    if( pn && i < aParams.GetSize() && pOld->pIn )
    {
        // mark the whole line
        pOld->pIn->GetParser()->SetCol1( 0 );
        pOld->pIn->GetParser()->Error( ERRCODE_BASIC_BAD_DECLARATION, aName );
    }

    if( !pIn && pOld->pIn )
    {
        // Replace old entry with the new one
        nPos = pOld->nPos;
        nId  = pOld->nId;
        pIn  = pOld->pIn;

        // don't delete pOld twice, if it's stored in m_Data
        if (pOld == pIn->m_Data[nPos].get())
            pOld = nullptr;
        pIn->m_Data[nPos].reset(this);
    }
    delete pOld;
}

void SbiProcDef::setPropertyMode( PropertyMode ePropMode )
{
    mePropMode = ePropMode;
    if( mePropMode == PropertyMode::NONE )
        return;

    // Prop name = original scanned procedure name
    maPropName = aName;

    // CompleteProcName includes "Property xxx "
    // to avoid conflicts with other symbols
    OUString aCompleteProcName = u"Property "_ustr;
    switch( mePropMode )
    {
    case PropertyMode::Get:  aCompleteProcName += "Get "break;
    case PropertyMode::Let:  aCompleteProcName += "Let "break;
    case PropertyMode::Set:  aCompleteProcName += "Set "break;
    case PropertyMode::NONE: OSL_FAIL( "Illegal PropertyMode PropertyMode::NONE" ); break;
    }
    aCompleteProcName += aName;
    aName = aCompleteProcName;
}


SbiConstDef::SbiConstDef( const OUString& rName )
           : SbiSymDef( rName )
{
    nVal = 0; eType = SbxINTEGER;
}

void SbiConstDef::Set( double n, SbxDataType t )
{
    aVal.clear(); nVal = n; eType = t;
}

void SbiConstDef::Set( const OUString& n )
{
    aVal = n; nVal = 0; eType = SbxSTRING;
}

SbiConstDef::~SbiConstDef()
{}

SbiConstDef* SbiConstDef::GetConstDef()
{
    return this;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=96 H=99 G=97

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge