Commit f285c829 authored by Dick Hollenbeck's avatar Dick Hollenbeck
Browse files

S-expression in xnode.cpp

parent b6159391
Loading
Loading
Loading
Loading
+13 −0
Original line number Original line Diff line number Diff line
@@ -4,6 +4,19 @@ KiCad ChangeLog 2010
Please add newer entries at the top, list the date and your name with
Please add newer entries at the top, list the date and your name with
email address.
email address.


2010-Aug-7 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
++common
  * add xnode.cpp and xnode.h which can be used to output either an XML or
    S-expression document file.
  * Add class STREAM_OUTPUTFORMATTER which is a richio class which can write
    to any of the wxOutputStream derivatives, such as file, socket, zip, tar.
  * Added netlist.keywords
++eeschema
  * netform.cpp can now output S-expression OK, although I have it commented out
    pending the addition of a UI for it.


2010-Aug-4 UPDATE Dick Hollenbeck <dick@softplc.com>
2010-Aug-4 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
================================================================================
++eeschema netform.cpp:
++eeschema netform.cpp:
+40 −22
Original line number Original line Diff line number Diff line
@@ -147,18 +147,7 @@ const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, const char* quote
}
}




//-----<STRINGFORMATTER>----------------------------------------------------
int OUTPUTFORMATTER::vprint( const char* fmt,  va_list ap )  throw( IOError )

const char* STRINGFORMATTER::GetQuoteChar( const char* wrapee )
{
    // for what we are using STRINGFORMATTER for at this time, we can return
    // the nul string always.

    return "";
//    return OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, "\"" );
}

int STRINGFORMATTER::vprint( const char* fmt,  va_list ap )
{
{
    int ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
    int ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
    if( ret >= (int) buffer.size() )
    if( ret >= (int) buffer.size() )
@@ -168,13 +157,13 @@ int STRINGFORMATTER::vprint( const char* fmt, va_list ap )
    }
    }


    if( ret > 0 )
    if( ret > 0 )
        mystring.append( (const char*) &buffer[0] );
        write( &buffer[0], ret );


    return ret;
    return ret;
}
}




int STRINGFORMATTER::sprint( const char* fmt, ... )
int OUTPUTFORMATTER::sprint( const char* fmt, ... )  throw( IOError )
{
{
    va_list     args;
    va_list     args;


@@ -186,9 +175,8 @@ int STRINGFORMATTER::sprint( const char* fmt, ... )
}
}




int STRINGFORMATTER::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
int OUTPUTFORMATTER::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
{
{

#define NESTWIDTH           2   ///< how many spaces per nestLevel
#define NESTWIDTH           2   ///< how many spaces per nestLevel


    va_list     args;
    va_list     args;
@@ -200,17 +188,14 @@ int STRINGFORMATTER::Print( int nestLevel, const char* fmt, ... ) throw( IOError


    for( int i=0; i<nestLevel;  ++i )
    for( int i=0; i<nestLevel;  ++i )
    {
    {
        // no error checking needed, an exception indicates an error.
        result = sprint( "%*c", NESTWIDTH, ' ' );
        result = sprint( "%*c", NESTWIDTH, ' ' );
        if( result < 0 )
            break;


        total += result;
        total += result;
    }
    }


    if( result<0 || (result=vprint( fmt, args ))<0 )
    // no error checking needed, an exception indicates an error.
    {
    result = vprint( fmt, args );
        throw IOError( _("Error writing to STRINGFORMATTER") );
    }


    va_end( args );
    va_end( args );


@@ -219,6 +204,13 @@ int STRINGFORMATTER::Print( int nestLevel, const char* fmt, ... ) throw( IOError
}
}




//-----<STRINGFORMATTER>----------------------------------------------------

void STRINGFORMATTER::write( const char* aOutBuf, int aCount ) throw( IOError )
{
    mystring.append( aOutBuf, aCount );
}

void STRINGFORMATTER::StripUseless()
void STRINGFORMATTER::StripUseless()
{
{
    std::string  copy = mystring;
    std::string  copy = mystring;
@@ -234,3 +226,29 @@ void STRINGFORMATTER::StripUseless()
    }
    }
}
}



//-----<STREAM_OUTPUTFORMATTER>--------------------------------------

const char* STREAM_OUTPUTFORMATTER::GetQuoteChar( const char* wrapee )
{
    return OUTPUTFORMATTER::GetQuoteChar( wrapee, quoteChar );
}


void STREAM_OUTPUTFORMATTER::write( const char* aOutBuf, int aCount ) throw( IOError )
{
    int lastWrite;

    // This might delay awhile if you were writing to say a socket, but for
    // a file it should only go through the loop once.
    for( int total = 0;  total<aCount;  total += lastWrite )
    {
        lastWrite = os.Write( aOutBuf, aCount ).LastWrite();

        if( !os.IsOk() )
        {
            throw IOError( _( "OUTPUTSTREAM_OUTPUTFORMATTER write error" ) );
        }
    }
}
+61 −30
Original line number Original line Diff line number Diff line
@@ -24,46 +24,77 @@




#include "xnode.h"
#include "xnode.h"
#include "macros.h"


void XNODE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
    // output attributes first if they exist


    // output children if they exist.
typedef wxXmlProperty  XATTR;


    // output "contents" if it exists.  Use quote need checker to wrap contents if needed.
void XNODE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )

{
    // A good XML element will not have both children AND contents, usually one or the other.
    switch( GetType() )
    // children != attributes in the above statement.
    {

    case wxXML_ELEMENT_NODE:
//    for( XNODE*...
        out->Print( nestLevel, "(%s", CONV_TO_UTF8( GetName() ) );
        FormatContents( out, nestLevel );
        if( GetNext() )
            out->Print( 0, ")\n" );
        else
            out->Print( 0, ")" );
        break;

    default:
        FormatContents( out, nestLevel );
    }
}
}




void XNODE::FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
void XNODE::FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
{
    // overridden in ELEM_HOLDER
    std::string utf8;
}
    const char* quote;



void XATTR::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
    // output attributes first if they exist
    // output attributes first if they exist
    for( XATTR* attr = (XATTR*) GetAttributes();  attr;  attr = (XATTR*) attr->GetNext() )
    {
        utf8  = CONV_TO_UTF8( attr->GetValue() );   // capture the content
        quote = out->GetQuoteChar( utf8.c_str() );


    // output children if they exist.
        out->Print( 0, " (%s %s%s%s)",

            // attr names should never need quoting, no spaces, we designed the file.
    // output "contents" if it exists.  Use quote need checker to wrap contents if needed.
            CONV_TO_UTF8( attr->GetName() ),
            quote, utf8.c_str(), quote );
    }


    // A good XML element will not have both children AND contents, usually one or the other.
    // we only expect to have used one of two types here:
    // children != attributes in the above statement.
    switch( GetType() )
    {
    case wxXML_ELEMENT_NODE:


//    for( XNODE*...
        // output children if they exist.
        for( XNODE* kid = (XNODE*) GetChildren();  kid;  kid = (XNODE*) kid->GetNext() )
        {
            if( kid->GetType() != wxXML_TEXT_NODE )
            {
                if( kid == GetChildren() )
                    out->Print( 0, "\n" );
                kid->Format( out, nestLevel+1 );
            }
            else
            {
                kid->Format( out, 0 );
            }
            }
        }
        break;


    case wxXML_TEXT_NODE:
        utf8  = CONV_TO_UTF8( GetContent() );
        quote = out->GetQuoteChar( utf8.c_str() );
        out->Print( 0, " %s%s%s", quote, utf8.c_str(), quote );
        break;


void XATTR::FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    default:
{
        ;   // not supported
    // overridden in ELEM_HOLDER
    }
}
}




+100 −61
Original line number Original line Diff line number Diff line
@@ -190,7 +190,6 @@ class EXPORT_HELP
     */
     */
    void writeListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList );
    void writeListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList );



    /**
    /**
     * Function makeGenericRoot
     * Function makeGenericRoot
     * builds the entire document tree for the generic export.  This is factored
     * builds the entire document tree for the generic export.  This is factored
@@ -392,6 +391,12 @@ static bool sortPinsByNum( NETLIST_OBJECT* aPin1, NETLIST_OBJECT* aPin2 )
    return RefDesStringCompare( aPin1->GetPinNumText(), aPin2->GetPinNumText() ) < 0;
    return RefDesStringCompare( aPin1->GetPinNumText(), aPin2->GetPinNumText() ) < 0;
}
}


static bool sortPinsByNumber( LIB_PIN* aPin1, LIB_PIN* aPin2 )
{
    // return "lhs < rhs"
    return RefDesStringCompare( aPin1->GetNumber(), aPin2->GetNumber() ) < 0;
}



void EXPORT_HELP::sprintPinNetName( wxString* aResult,
void EXPORT_HELP::sprintPinNetName( wxString* aResult,
                        const wxString& aNetNameFormat, NETLIST_OBJECT* aPin )
                        const wxString& aNetNameFormat, NETLIST_OBJECT* aPin )
@@ -626,7 +631,7 @@ XNODE* EXPORT_HELP::makeGenericLibraries()
        XNODE*      xlibrary;
        XNODE*      xlibrary;


        xlibs->AddChild( xlibrary = node( wxT( "library" ) ) );
        xlibs->AddChild( xlibrary = node( wxT( "library" ) ) );
        xlibrary->AddProperty( wxT( "logical" ), lib->GetLogicalName() );
        xlibrary->AddAttribute( wxT( "logical" ), lib->GetLogicalName() );
        xlibrary->AddChild( node( wxT( "uri" ),  lib->GetFullFileName() ) );
        xlibrary->AddChild( node( wxT( "uri" ),  lib->GetFullFileName() ) );


        // @todo: add more fun stuff here
        // @todo: add more fun stuff here
@@ -651,7 +656,6 @@ XNODE* EXPORT_HELP::makeGenericLibParts()
    wxString    sDescr    = wxT( "description" );
    wxString    sDescr    = wxT( "description" );
    wxString    sDocs     = wxT( "docs" );
    wxString    sDocs     = wxT( "docs" );



    LIB_PIN_LIST    pinList;
    LIB_PIN_LIST    pinList;
    LIB_FIELD_LIST  fieldList;
    LIB_FIELD_LIST  fieldList;


@@ -666,8 +670,8 @@ XNODE* EXPORT_HELP::makeGenericLibParts()


        XNODE*      xlibpart;
        XNODE*      xlibpart;
        xlibparts->AddChild( xlibpart = node( sLibpart ) );
        xlibparts->AddChild( xlibpart = node( sLibpart ) );
        xlibpart->AddProperty( sLib, library->GetLogicalName() );
        xlibpart->AddAttribute( sLib, library->GetLogicalName() );
        xlibpart->AddProperty( sPart, lcomp->GetName()  );
        xlibpart->AddAttribute( sPart, lcomp->GetName()  );


        //----- show the important properties -------------------------
        //----- show the important properties -------------------------
        if( !lcomp->GetDescription().IsEmpty() )
        if( !lcomp->GetDescription().IsEmpty() )
@@ -693,7 +697,7 @@ XNODE* EXPORT_HELP::makeGenericLibParts()
            {
            {
                XNODE*     xfield;
                XNODE*     xfield;
                xfields->AddChild( xfield = node( sField, fieldList[i].m_Text ) );
                xfields->AddChild( xfield = node( sField, fieldList[i].m_Text ) );
                xfield->AddProperty( sName, fieldList[i].m_Name );
                xfield->AddAttribute( sName, fieldList[i].m_Name );
            }
            }
        }
        }


@@ -701,7 +705,7 @@ XNODE* EXPORT_HELP::makeGenericLibParts()
        pinList.clear();
        pinList.clear();
        lcomp->GetPins( pinList, 0, 0 );
        lcomp->GetPins( pinList, 0, 0 );


        // sort the pin list here?
        sort( pinList.begin(), pinList.end(), sortPinsByNumber );


        if( pinList.size() )
        if( pinList.size() )
        {
        {
@@ -713,7 +717,7 @@ XNODE* EXPORT_HELP::makeGenericLibParts()
                XNODE*     pin;
                XNODE*     pin;


                pins->AddChild( pin = node( sPin ) );
                pins->AddChild( pin = node( sPin ) );
                pin->AddProperty( sNum, pinList[i]->GetNumber() );
                pin->AddAttribute( sNum, pinList[i]->GetNumber() );


                // caution: construction work site here, drive slowly
                // caution: construction work site here, drive slowly
            }
            }
@@ -796,14 +800,14 @@ XNODE* EXPORT_HELP::makeGenericListOfNets()
        {
        {
            xnets->AddChild( xnet = node( sNet ) );
            xnets->AddChild( xnet = node( sNet ) );
            netCodeTxt.Printf( sFmtd, netCode );
            netCodeTxt.Printf( sFmtd, netCode );
            xnet->AddProperty( sCode, netCodeTxt );
            xnet->AddAttribute( sCode, netCodeTxt );
            xnet->AddProperty( sName, netName );
            xnet->AddAttribute( sName, netName );
        }
        }


        XNODE*      xnode;
        XNODE*      xnode;
        xnet->AddChild( xnode = node( sNode ) );
        xnet->AddChild( xnode = node( sNode ) );
        xnode->AddProperty( sRef, ref );
        xnode->AddAttribute( sRef, ref );
        xnode->AddProperty( sPin,  nitem->GetPinNumText() );
        xnode->AddAttribute( sPin,  nitem->GetPinNumText() );
    }
    }


    return xnets;
    return xnets;
@@ -814,7 +818,7 @@ XNODE* EXPORT_HELP::makeGenericRoot()
{
{
    XNODE*      xroot = node( wxT( "export" ) );
    XNODE*      xroot = node( wxT( "export" ) );


    xroot->AddProperty( wxT( "version" ), wxT( "D" ) );
    xroot->AddAttribute( wxT( "version" ), wxT( "D" ) );


    // add the "design" header
    // add the "design" header
    xroot->AddChild( makeGenericDesignHeader() );
    xroot->AddChild( makeGenericDesignHeader() );
@@ -890,7 +894,7 @@ XNODE* EXPORT_HELP::makeGenericComponents()
            // an element.
            // an element.


            xcomps->AddChild( xcomp = node( sComponent ) );
            xcomps->AddChild( xcomp = node( sComponent ) );
            xcomp->AddProperty( sRef, comp->GetRef( path ) );
            xcomp->AddAttribute( sRef, comp->GetRef( path ) );


            xcomp->AddChild( node( sValue, comp->GetField( VALUE )->m_Text ) );
            xcomp->AddChild( node( sValue, comp->GetField( VALUE )->m_Text ) );


@@ -917,7 +921,7 @@ XNODE* EXPORT_HELP::makeGenericComponents()
                    {
                    {
                        XNODE*  xfield;
                        XNODE*  xfield;
                        xfields->AddChild( xfield = node( sField, f->m_Text ) );
                        xfields->AddChild( xfield = node( sField, f->m_Text ) );
                        xfield->AddProperty( sName, f->m_Name );
                        xfield->AddAttribute( sName, f->m_Name );
                    }
                    }
                }
                }
            }
            }
@@ -930,13 +934,13 @@ XNODE* EXPORT_HELP::makeGenericComponents()
            // is merely the library name minus path and extension.
            // is merely the library name minus path and extension.
            LIB_COMPONENT* entry = CMP_LIBRARY::FindLibraryComponent( comp->m_ChipName );
            LIB_COMPONENT* entry = CMP_LIBRARY::FindLibraryComponent( comp->m_ChipName );
            if( entry )
            if( entry )
                xlibsource->AddProperty( sLib, entry->GetLibrary()->GetLogicalName() );
                xlibsource->AddAttribute( sLib, entry->GetLibrary()->GetLogicalName() );
            xlibsource->AddProperty( sPart, comp->m_ChipName );
            xlibsource->AddAttribute( sPart, comp->m_ChipName );


            XNODE* xsheetpath;
            XNODE* xsheetpath;
            xcomp->AddChild( xsheetpath = node( sSheetPath ) );
            xcomp->AddChild( xsheetpath = node( sSheetPath ) );
            xsheetpath->AddProperty( sNames, path->PathHumanReadable() );
            xsheetpath->AddAttribute( sNames, path->PathHumanReadable() );
            xsheetpath->AddProperty( sTStamps, path->Path() );
            xsheetpath->AddAttribute( sTStamps, path->Path() );


            timeStamp.Printf( sTSFmt, comp->m_TimeStamp );
            timeStamp.Printf( sTSFmt, comp->m_TimeStamp );
            xcomp->AddChild( node( sTStamp, timeStamp ) );
            xcomp->AddChild( node( sTStamp, timeStamp ) );
@@ -946,10 +950,45 @@ XNODE* EXPORT_HELP::makeGenericComponents()
    return xcomps;
    return xcomps;
}
}


#include <wx/wfstream.h>        // wxFFileOutputStream


bool EXPORT_HELP::WriteGENERICNetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName )
bool EXPORT_HELP::WriteGENERICNetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName )
{
{
#if 1
#if 0

    // this code seems to work now, for S-expression support.

    bool rc = false;
    wxFFileOutputStream os( aOutFileName, wxT( "wt" ) );

    if( !os.IsOk() )
    {
    L_error:
        wxString msg = _( "Failed to create file " ) + aOutFileName;
        DisplayError( frame, msg );
    }
    else
    {
        XNODE*  xroot = makeGenericRoot();

        try
        {
            STREAM_OUTPUTFORMATTER  outputFormatter( os );
            xroot->Format( &outputFormatter, 0 );
        }
        catch( IOError ioe )
        {
            delete xroot;
            goto L_error;
        }

        delete xroot;
        rc = true;
    }

    return rc;

#elif 1
    // output the XML format netlist.
    // output the XML format netlist.
    wxXmlDocument   xdoc;
    wxXmlDocument   xdoc;


+35 −0
Original line number Original line Diff line number Diff line
code
comp
components
datasheet
date
description
design
docs
export
field
fields
footprint
lib
libpart
libraries
library
libsource
name
names
net
nets
node
num
part
pin
pins
ref
sheetpath
source
tool
tstamp
tstamps
uri
value
version
Loading