S-expression in xnode.cpp

This commit is contained in:
Dick Hollenbeck 2010-08-07 19:31:07 -05:00
parent b615939120
commit f285c8295b
9 changed files with 339 additions and 254 deletions

View File

@ -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:

View File

@ -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" ) );
}
}
}

View File

@ -24,46 +24,77 @@
#include "xnode.h" #include "xnode.h"
#include "macros.h"
typedef wxXmlProperty XATTR;
void XNODE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void XNODE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
// output attributes first if they exist switch( GetType() )
{
case wxXML_ELEMENT_NODE:
out->Print( nestLevel, "(%s", CONV_TO_UTF8( GetName() ) );
FormatContents( out, nestLevel );
if( GetNext() )
out->Print( 0, ")\n" );
else
out->Print( 0, ")" );
break;
// output children if they exist. default:
FormatContents( out, nestLevel );
// output "contents" if it exists. Use quote need checker to wrap contents if needed. }
// A good XML element will not have both children AND contents, usually one or the other.
// children != attributes in the above statement.
// for( XNODE*...
} }
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.
CONV_TO_UTF8( attr->GetName() ),
quote, utf8.c_str(), quote );
}
// output "contents" if it exists. Use quote need checker to wrap contents if needed. // we only expect to have used one of two types here:
switch( GetType() )
{
case wxXML_ELEMENT_NODE:
// A good XML element will not have both children AND contents, usually one or the other. // output children if they exist.
// children != attributes in the above statement. 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;
// for( XNODE*... 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;
default:
void XATTR::FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) ; // not supported
{ }
// overridden in ELEM_HOLDER
} }

View File

@ -190,46 +190,45 @@ 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
* out here so we can write the tree in either S-expression file format * out here so we can write the tree in either S-expression file format
* or in XML if we put the tree built here into a wxXmlDocument. * or in XML if we put the tree built here into a wxXmlDocument.
*/ */
XNODE* makeGenericRoot(); XNODE* makeGenericRoot();
/** /**
* Function makeGenericComponents * Function makeGenericComponents
* returns a sub-tree holding all the schematic components. * returns a sub-tree holding all the schematic components.
*/ */
XNODE* makeGenericComponents(); XNODE* makeGenericComponents();
/** /**
* Function makeGenericDesignHeader * Function makeGenericDesignHeader
* fills out a project "design" header into an XML node. * fills out a project "design" header into an XML node.
* @return XNODE* - the design header * @return XNODE* - the design header
*/ */
XNODE* makeGenericDesignHeader(); XNODE* makeGenericDesignHeader();
/** /**
* Function makeGenericLibParts * Function makeGenericLibParts
* fills out an XML node with the unique library parts and returns it. * fills out an XML node with the unique library parts and returns it.
*/ */
XNODE* makeGenericLibParts(); XNODE* makeGenericLibParts();
/** /**
* Function makeGenericListOfNets * Function makeGenericListOfNets
* fills out an XML node with a list of nets and returns it. * fills out an XML node with a list of nets and returns it.
*/ */
XNODE* makeGenericListOfNets(); XNODE* makeGenericListOfNets();
/** /**
* Function makeGenericLibraries * Function makeGenericLibraries
* fills out an XML node with a list of used libraries and returns it. * fills out an XML node with a list of used libraries and returns it.
* Must have called makeGenericLibParts() before this function. * Must have called makeGenericLibParts() before this function.
*/ */
XNODE* makeGenericLibraries(); XNODE* makeGenericLibraries();
public: public:
@ -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 )
@ -577,7 +582,7 @@ static XNODE* node( const wxString& aName, const wxString& aTextualContent = wxE
XNODE* EXPORT_HELP::makeGenericDesignHeader() XNODE* EXPORT_HELP::makeGenericDesignHeader()
{ {
XNODE* xdesign = node( wxT("design") ); XNODE* xdesign = node( wxT("design") );
char date[128]; char date[128];
DateAndTime( date ); DateAndTime( date );
@ -616,17 +621,17 @@ XNODE* EXPORT_HELP::makeGenericDesignHeader()
} }
XNODE* EXPORT_HELP::makeGenericLibraries() XNODE* EXPORT_HELP::makeGenericLibraries()
{ {
XNODE* xlibs = node( wxT( "libraries" ) ); // auto_ptr XNODE* xlibs = node( wxT( "libraries" ) ); // auto_ptr
for( std::set<void*>::iterator it = m_Libraries.begin(); it!=m_Libraries.end(); ++it ) for( std::set<void*>::iterator it = m_Libraries.begin(); it!=m_Libraries.end(); ++it )
{ {
CMP_LIBRARY* lib = (CMP_LIBRARY*) *it; CMP_LIBRARY* lib = (CMP_LIBRARY*) *it;
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
@ -636,7 +641,7 @@ XNODE* EXPORT_HELP::makeGenericLibraries()
} }
XNODE* EXPORT_HELP::makeGenericLibParts() XNODE* EXPORT_HELP::makeGenericLibParts()
{ {
XNODE* xlibparts = node( wxT( "libparts" ) ); // auto_ptr XNODE* xlibparts = node( wxT( "libparts" ) ); // auto_ptr
wxString sLibpart = wxT( "libpart" ); wxString sLibpart = wxT( "libpart" );
@ -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
} }
@ -724,7 +728,7 @@ XNODE* EXPORT_HELP::makeGenericLibParts()
} }
XNODE* EXPORT_HELP::makeGenericListOfNets() XNODE* EXPORT_HELP::makeGenericListOfNets()
{ {
XNODE* xnets = node( wxT( "nets" ) ); // auto_ptr if exceptions ever get used. XNODE* xnets = node( wxT( "nets" ) ); // auto_ptr if exceptions ever get used.
wxString netCodeTxt; wxString netCodeTxt;
@ -796,25 +800,25 @@ 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;
} }
XNODE* EXPORT_HELP::makeGenericRoot() 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() );
@ -832,11 +836,11 @@ XNODE* EXPORT_HELP::makeGenericRoot()
} }
XNODE* EXPORT_HELP::makeGenericComponents() XNODE* EXPORT_HELP::makeGenericComponents()
{ {
XNODE* xcomps = node( wxT( "components" ) ); XNODE* xcomps = node( wxT( "components" ) );
wxString timeStamp; wxString timeStamp;
// some strings we need many times, but don't want to construct more // some strings we need many times, but don't want to construct more
// than once for performance. These are used within loops so the // than once for performance. These are used within loops so the
@ -844,25 +848,25 @@ XNODE* EXPORT_HELP::makeGenericComponents()
// they were in a nested scope. // they were in a nested scope.
// these are actually constructor invocations, not assignments as it appears: // these are actually constructor invocations, not assignments as it appears:
wxString sFields = wxT( "fields" ); wxString sFields = wxT( "fields" );
wxString sField = wxT( "field" ); wxString sField = wxT( "field" );
wxString sComponent = wxT( "comp" ); // use "part" ? wxString sComponent = wxT( "comp" ); // use "part" ?
wxString sName = wxT( "name" ); wxString sName = wxT( "name" );
wxString sRef = wxT( "ref" ); wxString sRef = wxT( "ref" );
wxString sPins = wxT( "pins" ); wxString sPins = wxT( "pins" );
wxString sPin = wxT( "pin" ); wxString sPin = wxT( "pin" );
wxString sValue = wxT( "value" ); wxString sValue = wxT( "value" );
wxString sSheetPath = wxT( "sheetpath" ); wxString sSheetPath = wxT( "sheetpath" );
wxString sFootprint = wxT( "footprint" ); wxString sFootprint = wxT( "footprint" );
wxString sDatasheet = wxT( "datasheet" ); wxString sDatasheet = wxT( "datasheet" );
wxString sTStamp = wxT( "tstamp" ); wxString sTStamp = wxT( "tstamp" );
wxString sTStamps = wxT( "tstamps" ); wxString sTStamps = wxT( "tstamps" );
wxString sTSFmt = wxT( "%8.8lX" ); // comp->m_TimeStamp wxString sTSFmt = wxT( "%8.8lX" ); // comp->m_TimeStamp
wxString sLibSource = wxT( "libsource" ); wxString sLibSource = wxT( "libsource" );
wxString sLibPart = wxT( "libpart" ); wxString sLibPart = wxT( "libpart" );
wxString sLib = wxT( "lib" ); wxString sLib = wxT( "lib" );
wxString sPart = wxT( "part" ); wxString sPart = wxT( "part" );
wxString sNames = wxT( "names" ); wxString sNames = wxT( "names" );
m_ReferencesAlreadyFound.Clear(); m_ReferencesAlreadyFound.Clear();
@ -882,7 +886,7 @@ XNODE* EXPORT_HELP::makeGenericComponents()
schItem = comp; schItem = comp;
XNODE* xcomp; // current component being constructed XNODE* xcomp; // current component being constructed
// Output the component's elments in order of expected access frequency. // Output the component's elments in order of expected access frequency.
// This may not always look best, but it will allow faster execution // This may not always look best, but it will allow faster execution
@ -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 ) );
@ -905,7 +909,7 @@ XNODE* EXPORT_HELP::makeGenericComponents()
// container element if there are any <field>s. // container element if there are any <field>s.
if( comp->GetFieldCount() > MANDATORY_FIELDS ) if( comp->GetFieldCount() > MANDATORY_FIELDS )
{ {
XNODE* xfields; XNODE* xfields;
xcomp->AddChild( xfields = node( sFields ) ); xcomp->AddChild( xfields = node( sFields ) );
for( int fldNdx = MANDATORY_FIELDS; fldNdx < comp->GetFieldCount(); ++fldNdx ) for( int fldNdx = MANDATORY_FIELDS; fldNdx < comp->GetFieldCount(); ++fldNdx )
@ -915,14 +919,14 @@ XNODE* EXPORT_HELP::makeGenericComponents()
// only output a field if non empty // only output a field if non empty
if( !f->m_Text.IsEmpty() ) if( !f->m_Text.IsEmpty() )
{ {
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 );
} }
} }
} }
XNODE* xlibsource; XNODE* xlibsource;
xcomp->AddChild( xlibsource = node( sLibSource ) ); xcomp->AddChild( xlibsource = node( sLibSource ) );
// "logical" library name, which is in anticipation of a better search // "logical" library name, which is in anticipation of a better search
@ -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
eeschema/netlist.keywords Normal file
View File

@ -0,0 +1,35 @@
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

View File

@ -148,14 +148,14 @@ public:
/** /**
* Function Rewind * Function Rewind
* a wrapper to the standard function rewind. * a wrapper to the standard function rewind.
* also clear the current line number * also clear the current line number
*/ */
void Rewind() void Rewind()
{ {
rewind( fp ); rewind( fp );
lineNum = 0; lineNum = 0;
} }
}; };
@ -201,17 +201,43 @@ public:
/** /**
* Class OUTPUTFORMATTER * Class OUTPUTFORMATTER
* is an interface (abstract class) used to output ASCII text in a convenient * is an important interface (abstract) class used to output UTF8 text in a convenient
* way. The primary interface is printf() like but with support for indentation * way. The primary interface is "printf() - like" but with support for indentation
* control. The destination of the 8 bit wide text is up to the implementer. * control. The destination of the 8 bit wide text is up to the implementer.
* <p>
* The implementer only has to implement the write() function, but can also optionaly
* re-implement GetQuoteChar().
* <p>
* If you want to output a wxString, then use CONV_TO_UTF8() on it before passing * If you want to output a wxString, then use CONV_TO_UTF8() on it before passing
* it as an argument to Print(). * it as an argument to Print().
* <p> * <p>
* Since this is an abstract interface, only classes derived from this one * Since this is an abstract interface, only classes derived from this one
* will be the implementations. * may actually be used.
*/ */
class OUTPUTFORMATTER class OUTPUTFORMATTER
{ {
std::vector<char> buffer;
int sprint( const char* fmt, ... ) throw( IOError );
int vprint( const char* fmt, va_list ap ) throw( IOError );
protected:
OUTPUTFORMATTER( int aReserve = 300 ) :
buffer( aReserve, '\0' )
{
}
/**
* Function write
* should be coded in the interface implementation (derived) classes.
*
* @param aOutBuf is the start of a byte buffer to write.
* @param aCount tells how many bytes to write.
* @throw IOError, if there is a problem outputting, such as a full disk.
*/
virtual void write( const char* aOutBuf, int aCount ) throw( IOError ) = 0;
#if defined(__GNUG__) // The GNU C++ compiler defines this #if defined(__GNUG__) // The GNU C++ compiler defines this
@ -238,7 +264,7 @@ public:
* @return int - the number of characters output. * @return int - the number of characters output.
* @throw IOError, if there is a problem outputting, such as a full disk. * @throw IOError, if there is a problem outputting, such as a full disk.
*/ */
virtual int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError ) = 0; int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError );
/** /**
* Function GetQuoteChar * Function GetQuoteChar
@ -256,7 +282,10 @@ public:
* @return const char* - the quote_char as a single character string, or "" * @return const char* - the quote_char as a single character string, or ""
* if the wrapee does not need to be wrapped. * if the wrapee does not need to be wrapped.
*/ */
virtual const char* GetQuoteChar( const char* wrapee ) = 0; virtual const char* GetQuoteChar( const char* wrapee )
{
return GetQuoteChar( wrapee, "\"" );
}
virtual ~OUTPUTFORMATTER() {} virtual ~OUTPUTFORMATTER() {}
@ -283,12 +312,8 @@ public:
*/ */
class STRINGFORMATTER : public OUTPUTFORMATTER class STRINGFORMATTER : public OUTPUTFORMATTER
{ {
std::vector<char> buffer;
std::string mystring; std::string mystring;
int sprint( const char* fmt, ... );
int vprint( const char* fmt, va_list ap );
public: public:
/** /**
@ -296,11 +321,10 @@ public:
* reserves space in the buffer * reserves space in the buffer
*/ */
STRINGFORMATTER( int aReserve = 300 ) : STRINGFORMATTER( int aReserve = 300 ) :
buffer( aReserve, '\0' ) OUTPUTFORMATTER( aReserve )
{ {
} }
/** /**
* Function Clear * Function Clear
* clears the buffer and empties the internal string. * clears the buffer and empties the internal string.
@ -316,16 +340,47 @@ public:
*/ */
void StripUseless(); void StripUseless();
std::string GetString() std::string GetString()
{ {
return mystring; return mystring;
} }
//-----<OUTPUTFORMATTER>------------------------------------------------
protected:
void write( const char* aOutBuf, int aCount ) throw( IOError );
//-----</OUTPUTFORMATTER>-----------------------------------------------
};
/**
* Class STREAM_OUTPUTFORMATTER
* implements OUTPUTFORMATTER to a wxWidgets wxOutputStream. The stream is
* neither opened nor closed by this class.
*/
class STREAM_OUTPUTFORMATTER : public OUTPUTFORMATTER
{
wxOutputStream& os;
char quoteChar[2];
public:
/**
* Constructor STREAM_OUTPUTFORMATTER
* can take any number of wxOutputStream derivations, so it can write
* to a file, socket, or zip file.
*/
STREAM_OUTPUTFORMATTER( wxOutputStream& aStream, char aQuoteChar = '"' ) :
os( aStream )
{
quoteChar[0] = aQuoteChar;
quoteChar[1] = 0;
}
//-----<OUTPUTFORMATTER>------------------------------------------------ //-----<OUTPUTFORMATTER>------------------------------------------------
int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError );
const char* GetQuoteChar( const char* wrapee ); const char* GetQuoteChar( const char* wrapee );
protected:
void write( const char* aOutBuf, int aCount ) throw( IOError );
//-----</OUTPUTFORMATTER>----------------------------------------------- //-----</OUTPUTFORMATTER>-----------------------------------------------
}; };

View File

@ -25,55 +25,10 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "richio.h" #include "richio.h"
// #define WXUSINGDLL
#include <wx/xml/xml.h> #include <wx/xml/xml.h>
// These are classes for eXporting document trees, and thus have names
// starting with X. They can export either in XML or S-expression format.
/**
* Class XATTR
* holds an XML or S-expression attribute/child value. It is used for eXporting
* a document tree in EITHER XML or S-expression.
*/
class XATTR : public wxXmlProperty // use wxXmlAttribute for wx >= 2.9
{
public:
XATTR() :
wxXmlProperty()
{
}
XATTR( const wxString& aName, const wxString& aValue ) :
wxXmlProperty( aName, aValue )
{
}
/**
* Function Format
* writes this object as UTF8 out to an OUTPUTFORMATTER as an S-expression
* @param out The formatter to write to.
* @param nestLevel A multiple of the number of spaces to preceed the output with.
* @throw IOError if a system error writing the output, such as a full disk.
*/
virtual void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError );
/**
* Function FormatContents
* writes the contents of object as UTF8 out to an OUTPUTFORMATTER as an S-expression
* This is the same as Format() except that the outer wrapper is not included.
* @param out The formatter to write to.
* @param nestLevel A multiple of the number of spaces to preceed the output with.
* @throw IOError if a system error writing the output, such as a full disk.
*/
virtual void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError );
};
/** /**
* Class XNODE * Class XNODE
@ -88,13 +43,11 @@ public:
{ {
} }
XNODE( wxXmlNodeType aType, const wxString& aName, const wxString& aContent = wxEmptyString ) : XNODE( wxXmlNodeType aType, const wxString& aName, const wxString& aContent = wxEmptyString ) :
wxXmlNode( NULL, aType, aName, aContent ) wxXmlNode( NULL, aType, aName, aContent )
{ {
} }
/** /**
* Function Format * Function Format
* writes this object as UTF8 out to an OUTPUTFORMATTER as an S-expression * writes this object as UTF8 out to an OUTPUTFORMATTER as an S-expression
@ -104,7 +57,6 @@ public:
*/ */
virtual void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ); virtual void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError );
/** /**
* Function FormatContents * Function FormatContents
* writes the contents of object as UTF8 out to an OUTPUTFORMATTER as an S-expression * writes the contents of object as UTF8 out to an OUTPUTFORMATTER as an S-expression

View File

@ -52,7 +52,9 @@
#include "specctra.h" #include "specctra.h"
#include <wx/ffile.h> //#include <wx/ffile.h>
#include <wx/wfstream.h> // wxFFileOutputStream
#include "build_version.h" #include "build_version.h"
@ -3850,81 +3852,42 @@ void SPECCTRA_DB::doSUPPLY_PIN( SUPPLY_PIN* growth ) throw( IOError )
} }
int SPECCTRA_DB::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
{
va_list args;
va_start( args, fmt );
int result = 0;
int total = 0;
for( int i=0; i<nestLevel; ++i )
{
result = fprintf( fp, "%*c", NESTWIDTH, ' ' );
if( result < 0 )
break;
total += result;
}
if( result<0 || (result=vfprintf( fp, fmt, args ))<0 )
{
ThrowIOError( _("System file error writing to file \"%s\""), GetChars(filename) );
}
va_end( args );
total += result;
return total;
}
const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee )
{
return OUTPUTFORMATTER::GetQuoteChar( wrapee, quote_char.c_str() );
}
void SPECCTRA_DB::ExportPCB( wxString filename, bool aNameChange ) throw( IOError ) void SPECCTRA_DB::ExportPCB( wxString filename, bool aNameChange ) throw( IOError )
{ {
fp = wxFopen( filename, wxT("w") );
if( !fp )
{
ThrowIOError( _("Unable to open file \"%s\""), GetChars(filename) );
}
if( pcb ) if( pcb )
{ {
wxFFileOutputStream os( filename, wxT( "wt" ) );
if( !os.IsOk() )
{
ThrowIOError( _("Unable to open file \"%s\""), GetChars(filename) );
}
STREAM_OUTPUTFORMATTER outputFormatter( os, quote_char[0] );
if( aNameChange ) if( aNameChange )
pcb->pcbname = CONV_TO_UTF8(filename); pcb->pcbname = CONV_TO_UTF8(filename);
pcb->Format( this, 0 ); pcb->Format( &outputFormatter, 0 );
} }
// if an exception is thrown by Format, then ~SPECCTRA_DB() will close
// the file.
fclose( fp );
fp = 0;
} }
void SPECCTRA_DB::ExportSESSION( wxString filename ) void SPECCTRA_DB::ExportSESSION( wxString filename )
{ {
fp = wxFopen( filename, wxT("w") );
if( !fp )
{
ThrowIOError( _("Unable to open file \"%s\""), GetChars(filename) );
}
if( session ) if( session )
session->Format( this, 0 ); {
wxFFileOutputStream os( filename, wxT( "wt" ) );
fclose( fp ); if( !os.IsOk() )
fp = 0; {
ThrowIOError( _("Unable to open file \"%s\""), GetChars(filename) );
}
STREAM_OUTPUTFORMATTER outputFormatter( os, quote_char[0] );
session->Format( &outputFormatter, 0 );
}
} }

View File

@ -3970,7 +3970,7 @@ typedef boost::ptr_set<PADSTACK> PADSTACKSET;
* Class SPECCTRA_DB * Class SPECCTRA_DB
* holds a DSN data tree, usually coming from a DSN file. * holds a DSN data tree, usually coming from a DSN file.
*/ */
class SPECCTRA_DB : public OUTPUTFORMATTER class SPECCTRA_DB
{ {
/// specctra DSN keywords /// specctra DSN keywords
static const KEYWORD keywords[]; static const KEYWORD keywords[];
@ -3979,13 +3979,8 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
DSNLEXER* lexer; DSNLEXER* lexer;
PCB* pcb; PCB* pcb;
SESSION* session; SESSION* session;
FILE* fp;
wxString filename; wxString filename;
std::string quote_char; std::string quote_char;
bool modulesAreFlipped; bool modulesAreFlipped;
@ -4304,7 +4299,6 @@ public:
lexer = 0; lexer = 0;
pcb = 0; pcb = 0;
session = 0; session = 0;
fp = 0;
quote_char += '"'; quote_char += '"';
modulesAreFlipped = false; modulesAreFlipped = false;
} }
@ -4316,18 +4310,8 @@ public:
delete session; delete session;
deleteNETs(); deleteNETs();
if( fp )
fclose( fp );
} }
//-----<OUTPUTFORMATTER>-------------------------------------------------
int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError );
const char* GetQuoteChar( const char* wrapee );
//-----</OUTPUTFORMATTER>------------------------------------------------
static const char* TokenName( int aToken ); static const char* TokenName( int aToken );
@ -4354,11 +4338,6 @@ public:
} }
PCB* GetPCB() { return pcb; } PCB* GetPCB() { return pcb; }
void SetFILE( FILE* aFile )
{
fp = aFile;
}
/** /**
* Function SetSESSION * Function SetSESSION
* deletes any existing SESSION and replaces it with the given one. * deletes any existing SESSION and replaces it with the given one.