++eeschema netlist.cpp and netform.cpp:

* Found several speed optimizations in the netlist export code.
  * Fixed a bug in EXPORT_HELP::FindAllInstancesOfComponent() that I had broke.
  * Now sort the pins properly if they have pin numbers like A1 and A10,
    i.e. alphanumerics in them.
This commit is contained in:
Dick Hollenbeck 2010-08-03 00:18:50 -05:00
commit d24caad246
16 changed files with 485 additions and 378 deletions

View File

@ -4,18 +4,25 @@ 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-Jul-30 UPDATE Dick Hollenbeck <dick@softplc.com> 2010-Aug-3 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
++eeschema netlist.cpp and netform.cpp:
* Found several speed optimizations in the netlist export code.
* Now sort the pins properly if they have pin numbers like A1 and A10,
i.e. alphanumerics in them.
2010-Jul-30 & 31 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================ ================================================================================
++eeschema: ++eeschema:
* Now link with XML support within wxWidgets. * Now link with XML support within wxWidgets.
* Start of export the generic netlist in XML. Still need to rework the chain * Export the generic netlist in XML. Only the libpart elements are missing now.
loaded netlist plugin. Still need to rework the chain loaded netlist plugin, but may do that in XSL.
* OBJ_CMP_TO_LIST class now uses a std::string to hold the 8 bit string m_Ref, * OBJ_CMP_TO_LIST class now uses a std::string to hold the 8 bit string m_Ref,
but hides this behind accessors which provide for both Unicode and 8 bit but hides this behind accessors which provide for both Unicode and 8 bit
set and get functions. set and get functions.
* build_BOM.cpp retains the selected filename on subsequent runs as a default. * build_BOM.cpp retains the selected filename on subsequent runs as a default.
* Code cleaning, especially in build_BOM.cpp. * Code cleaning, especially in build_BOM.cpp.
* Will work tomorrow also.
2010-jul-27, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr> 2010-jul-27, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>

View File

@ -320,3 +320,113 @@ char* strupper( char* Text )
return Text; return Text;
} }
int RefDesStringCompare( const wxString& strFWord, const wxString& strSWord )
{
// The different sections of the first string
wxString strFWordBeg, strFWordMid, strFWordEnd;
// The different sections of the second string
wxString strSWordBeg, strSWordMid, strSWordEnd;
int isEqual = 0; // The numerical results of a string compare
int iReturn = 0; // The variable that is being returned
long lFirstDigit = 0; /* The converted middle section of the first
*string */
long lSecondDigit = 0; /* The converted middle section of the second
*string */
// Split the two strings into separate parts
SplitString( strFWord, &strFWordBeg, &strFWordMid, &strFWordEnd );
SplitString( strSWord, &strSWordBeg, &strSWordMid, &strSWordEnd );
// Compare the Beginning section of the strings
isEqual = strFWordBeg.CmpNoCase( strSWordBeg );
if( isEqual > 0 )
iReturn = 1;
else if( isEqual < 0 )
iReturn = -1;
else
{
// If the first sections are equal compare their digits
strFWordMid.ToLong( &lFirstDigit );
strSWordMid.ToLong( &lSecondDigit );
if( lFirstDigit > lSecondDigit )
iReturn = 1;
else if( lFirstDigit < lSecondDigit )
iReturn = -1;
else
{
// If the first two sections are equal compare the endings
isEqual = strFWordEnd.CmpNoCase( strSWordEnd );
if( isEqual > 0 )
iReturn = 1;
else if( isEqual < 0 )
iReturn = -1;
else
iReturn = 0;
}
}
return iReturn;
}
int SplitString( wxString strToSplit,
wxString* strBeginning,
wxString* strDigits,
wxString* strEnd )
{
// Clear all the return strings
strBeginning->Empty();
strDigits->Empty();
strEnd->Empty();
// There no need to do anything if the string is empty
if( strToSplit.length() == 0 )
return 0;
// Starting at the end of the string look for the first digit
int ii;
for( ii = (strToSplit.length() - 1); ii >= 0; ii-- )
{
if( isdigit( strToSplit[ii] ) )
break;
}
// If there were no digits then just set the single string
if( ii < 0 )
*strBeginning = strToSplit;
else
{
// Since there is at least one digit this is the trailing string
*strEnd = strToSplit.substr( ii + 1 );
// Go to the end of the digits
int position = ii + 1;
for( ; ii >= 0; ii-- )
{
if( !isdigit( strToSplit[ii] ) )
break;
}
// If all that was left was digits, then just set the digits string
if( ii < 0 )
*strDigits = strToSplit.substr( 0, position );
/* We were only looking for the last set of digits everything else is
*part of the preamble */
else
{
*strDigits = strToSplit.substr( ii + 1, position - ii - 1 );
*strBeginning = strToSplit.substr( 0, ii + 1 );
}
}
return 0;
}

View File

@ -71,12 +71,6 @@ static bool SortLabelsBySheet( const LABEL_OBJECT& obj1,
static void DeleteSubCmp( std::vector <OBJ_CMP_TO_LIST>& aList ); static void DeleteSubCmp( std::vector <OBJ_CMP_TO_LIST>& aList );
static int PrintListeGLabel( FILE* f, std::vector <LABEL_OBJECT>& aList ); static int PrintListeGLabel( FILE* f, std::vector <LABEL_OBJECT>& aList );
int RefDesStringCompare( const wxString& lhs, const wxString& rhs );
int SplitString( wxString strToSplit,
wxString* strBeginning,
wxString* strDigits,
wxString* strEnd );
// separator used in bom export to spreadsheet // separator used in bom export to spreadsheet
static char s_ExportSeparatorSymbol; static char s_ExportSeparatorSymbol;
@ -1049,122 +1043,3 @@ static int PrintListeGLabel( FILE* f, std::vector <LABEL_OBJECT>& aList )
} }
/* This function will act just like the strcmp function but correctly sort
* the numerical order in the string
* return -1 if first string is less than the second
* return 0 if the strings are equal
* return 1 if the first string is greater than the second
*/
int RefDesStringCompare( const wxString& strFWord, const wxString& strSWord )
{
// The different sections of the first string
wxString strFWordBeg, strFWordMid, strFWordEnd;
// The different sections of the second string
wxString strSWordBeg, strSWordMid, strSWordEnd;
int isEqual = 0; // The numerical results of a string compare
int iReturn = 0; // The variable that is being returned
long lFirstDigit = 0; /* The converted middle section of the first
*string */
long lSecondDigit = 0; /* The converted middle section of the second
*string */
// Split the two string into separate parts
SplitString( strFWord, &strFWordBeg, &strFWordMid, &strFWordEnd );
SplitString( strSWord, &strSWordBeg, &strSWordMid, &strSWordEnd );
// Compare the Beginning section of the strings
isEqual = strFWordBeg.CmpNoCase( strSWordBeg );
if( isEqual > 0 )
iReturn = 1;
else if( isEqual < 0 )
iReturn = -1;
else
{
// If the first sections are equal compare there digits
strFWordMid.ToLong( &lFirstDigit );
strSWordMid.ToLong( &lSecondDigit );
if( lFirstDigit > lSecondDigit )
iReturn = 1;
else if( lFirstDigit < lSecondDigit )
iReturn = -1;
else
{
// If the first two sections are equal compare the endings
isEqual = strFWordEnd.CmpNoCase( strSWordEnd );
if( isEqual > 0 )
iReturn = 1;
else if( isEqual < 0 )
iReturn = -1;
else
iReturn = 0;
}
}
return iReturn;
}
/* This is the function that breaks a string into three parts.
* The alphabetic preamble
* The numeric part
* Any alphabetic ending
* For example C10A is split to C 10 A
*/
int SplitString( wxString strToSplit,
wxString* strBeginning,
wxString* strDigits,
wxString* strEnd )
{
// Clear all the return strings
strBeginning->Clear();
strDigits->Clear();
strEnd->Clear();
// There no need to do anything if the string is empty
if( strToSplit.length() == 0 )
return 0;
// Starting at the end of the string look for the first digit
int ii;
for( ii = (strToSplit.length() - 1); ii >= 0; ii-- )
{
if( isdigit( strToSplit[ii] ) )
break;
}
// If there were no digits then just set the single string
if( ii < 0 )
*strBeginning = strToSplit;
else
{
// Since there is at least one digit this is the trailing string
*strEnd = strToSplit.substr( ii + 1 );
// Go to the end of the digits
int position = ii + 1;
for( ; ii >= 0; ii-- )
{
if( !isdigit( strToSplit[ii] ) )
break;
}
// If all that was left was digits, then just set the digits string
if( ii < 0 )
*strDigits = strToSplit.substr( 0, position );
/* We were only looking for the last set of digits everything else is
*part of the preamble */
else
{
*strDigits = strToSplit.substr( ii + 1, position - ii - 1 );
*strBeginning = strToSplit.substr( 0, ii + 1 );
}
}
return 0;
}

View File

@ -220,7 +220,7 @@ wxString SCH_SHEET_PATH::Path()
* (the "normal" path uses the time stamps which do not changes even when * (the "normal" path uses the time stamps which do not changes even when
* editing sheet parameters) * editing sheet parameters)
*/ */
wxString SCH_SHEET_PATH::PathHumanReadable() wxString SCH_SHEET_PATH::PathHumanReadable() const
{ {
wxString s, t; wxString s, t;
@ -355,6 +355,7 @@ SCH_ITEM* SCH_SHEET_PATH::MatchNextItem( wxFindReplaceData& aSearchData,
bool SCH_SHEET_PATH::operator=( const SCH_SHEET_PATH& d1 ) bool SCH_SHEET_PATH::operator=( const SCH_SHEET_PATH& d1 )
{ {
m_numSheets = d1.m_numSheets; m_numSheets = d1.m_numSheets;
unsigned i; unsigned i;
for( i = 0; i < m_numSheets; i++ ) for( i = 0; i < m_numSheets; i++ )
{ {
@ -370,10 +371,11 @@ bool SCH_SHEET_PATH::operator=( const SCH_SHEET_PATH& d1 )
} }
bool SCH_SHEET_PATH::operator==( const SCH_SHEET_PATH& d1 ) bool SCH_SHEET_PATH::operator==( const SCH_SHEET_PATH& d1 ) const
{ {
if( m_numSheets != d1.m_numSheets ) if( m_numSheets != d1.m_numSheets )
return false; return false;
for( unsigned i = 0; i < m_numSheets; i++ ) for( unsigned i = 0; i < m_numSheets; i++ )
{ {
if( m_sheets[i] != d1.m_sheets[i] ) if( m_sheets[i] != d1.m_sheets[i] )
@ -384,14 +386,23 @@ bool SCH_SHEET_PATH::operator==( const SCH_SHEET_PATH& d1 )
} }
bool SCH_SHEET_PATH::operator!=( const SCH_SHEET_PATH& d1 ) bool SCH_SHEET_PATH::operator!=( const SCH_SHEET_PATH& d1 ) const
{ {
if( m_numSheets != d1.m_numSheets ) if( m_numSheets != d1.m_numSheets )
return true; return true;
for( unsigned i = 0; i < m_numSheets; i++ ) for( unsigned i = 0; i < m_numSheets; i++ )
{ {
if( m_sheets[i] != d1.m_sheets[i] ) if( m_sheets[i] != d1.m_sheets[i] )
{
/*
printf( "micompare this:'%s' d1:'%s'\n",
CONV_TO_UTF8( PathHumanReadable() ),
CONV_TO_UTF8( d1.PathHumanReadable() ) );
*/
return true; return true;
}
} }
return false; return false;

View File

@ -150,7 +150,7 @@ public:
* stamps in the path. (Time stamps do not change even when editing * stamps in the path. (Time stamps do not change even when editing
* sheet parameters). * sheet parameters).
*/ */
wxString PathHumanReadable(); wxString PathHumanReadable() const;
/** Function BuildSheetPathInfoFromSheetPathValue /** Function BuildSheetPathInfoFromSheetPathValue
* Fill this with data to access to the hierarchical sheet known by its * Fill this with data to access to the hierarchical sheet known by its
@ -207,9 +207,9 @@ public:
bool operator=( const SCH_SHEET_PATH& d1 ); bool operator=( const SCH_SHEET_PATH& d1 );
bool operator==( const SCH_SHEET_PATH& d1 ); bool operator==( const SCH_SHEET_PATH& d1 ) const;
bool operator!=( const SCH_SHEET_PATH& d1 ); bool operator!=( const SCH_SHEET_PATH& d1 ) const;
}; };

View File

@ -10,7 +10,6 @@
#include "class_netlist_object.h" #include "class_netlist_object.h"
#if defined(DEBUG) #if defined(DEBUG)
#include <iostream> #include <iostream>
const char* ShowType( NetObjetType aType ) const char* ShowType( NetObjetType aType )
@ -84,10 +83,28 @@ void NETLIST_OBJECT::Show( std::ostream& out, int ndx )
if( !m_Label.IsEmpty() ) if( !m_Label.IsEmpty() )
out << " <label>" << m_Label.mb_str() << "</label>\n"; out << " <label>" << m_Label.mb_str() << "</label>\n";
out << " <sheetpath>" << m_SheetList.PathHumanReadable().mb_str() << "</sheetpath>\n";
switch( m_Type )
{
case NET_PIN:
out << " <refOfComp>" << ((SCH_COMPONENT*)m_Link)->GetRef(&m_SheetList).mb_str() << "</refOfComp>\n";
if( m_Comp )
m_Comp->Show( 1, out );
break;
default:
// not all the m_Comp classes have working Show functions.
;
}
/* was segfault-ing
if( m_Comp ) if( m_Comp )
m_Comp->Show( 1, out ); m_Comp->Show( 1, out ); // labels may not have good Show() funcs?
else else
out << " m_Comp==NULL\n"; out << " m_Comp==NULL\n";
*/
out << "</netItem>\n"; out << "</netItem>\n";
} }
@ -134,3 +151,4 @@ NETLIST_OBJECT::NETLIST_OBJECT( NETLIST_OBJECT& aSource )
NETLIST_OBJECT::~NETLIST_OBJECT() NETLIST_OBJECT::~NETLIST_OBJECT()
{ {
} }

View File

@ -6,6 +6,9 @@
#ifndef _CLASS_NETLIST_OBJECT_H_ #ifndef _CLASS_NETLIST_OBJECT_H_
#define _CLASS_NETLIST_OBJECT_H_ #define _CLASS_NETLIST_OBJECT_H_
#include "class_pin.h" // LIB_PIN::ReturnPinStringNum( m_PinNum )
/* Type of Net objects (wires, labels, pins...) */ /* Type of Net objects (wires, labels, pins...) */
enum NetObjetType { enum NetObjetType {
NET_ITEM_UNSPECIFIED, // only for not yet initialized instances NET_ITEM_UNSPECIFIED, // only for not yet initialized instances
@ -105,6 +108,17 @@ public:
void SetNet( int aNetCode ) { m_NetCode = aNetCode; } void SetNet( int aNetCode ) { m_NetCode = aNetCode; }
int GetNet() const { return m_NetCode; } int GetNet() const { return m_NetCode; }
/**
* Function GetPinNum
* returns a pin number in wxString form. Pin numbers are not always
* numbers. "A23" would be a valid pin number.
*/
wxString GetPinNumText()
{
// hide the ugliness in here, but do it inline.
return LIB_PIN::ReturnPinStringNum( m_PinNum );
}
}; };
#endif // _CLASS_NETLIST_OBJECT_H_ #endif // _CLASS_NETLIST_OBJECT_H_

View File

@ -1485,12 +1485,6 @@ wxString LIB_PIN::ReturnPinStringNum( long aPinNum )
} }
wxString LIB_PIN::GetNumber( void )
{
return ReturnPinStringNum( m_PinNum );
}
/** Function LIB_PIN::SetPinNumFromString() /** Function LIB_PIN::SetPinNumFromString()
* fill the buffer with pin num as a wxString * fill the buffer with pin num as a wxString
* Pin num is coded as a long * Pin num is coded as a long
@ -1772,3 +1766,16 @@ const char*** LIB_PIN::GetStyleSymbols()
return s_icons_Pins_Shapes; return s_icons_Pins_Shapes;
} }
#if defined(DEBUG)
void LIB_PIN::Show( int nestLevel, std::ostream& os )
{
NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
<< " num=\"" << GetNumber().mb_str()
<< '"' << "/>\n";
// NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
}
#endif

View File

@ -7,6 +7,7 @@
#ifndef CLASS_PIN_H #ifndef CLASS_PIN_H
#define CLASS_PIN_H #define CLASS_PIN_H
#include "classes_body_items.h"
#define TARGET_PIN_DIAM 12 /* Circle diameter drawn at the active end of #define TARGET_PIN_DIAM 12 /* Circle diameter drawn at the active end of
* pins */ * pins */
@ -114,6 +115,10 @@ public:
return wxT( "LIB_PIN" ); return wxT( "LIB_PIN" );
} }
#if defined(DEBUG)
void Show( int nestLevel, std::ostream& os ); // virtual override
#endif
/** /**
* Write pin object to a FILE in "*.lib" format. * Write pin object to a FILE in "*.lib" format.
@ -159,7 +164,12 @@ public:
*/ */
void ReturnPinStringNum( wxString& aStringBuffer ) const; void ReturnPinStringNum( wxString& aStringBuffer ) const;
wxString GetNumber();
wxString GetNumber()
{
return ReturnPinStringNum( m_PinNum );
}
/** Function ReturnPinStringNum (static function) /** Function ReturnPinStringNum (static function)
* Pin num is coded as a long or 4 ascii chars * Pin num is coded as a long or 4 ascii chars

View File

@ -934,7 +934,7 @@ void SCH_COMPONENT::Show( int nestLevel, std::ostream& os )
<< '"' << " chipName=\"" << '"' << " chipName=\""
<< CONV_TO_UTF8( m_ChipName ) << '"' << m_Pos << CONV_TO_UTF8( m_ChipName ) << '"' << m_Pos
<< " layer=\"" << m_Layer << " layer=\"" << m_Layer
<< '"' << "/>\n"; << '"' << ">\n";
// skip the reference, it's been output already. // skip the reference, it's been output already.
for( int i = 1; i < GetFieldCount(); ++i ) for( int i = 1; i < GetFieldCount(); ++i )

View File

@ -7,6 +7,8 @@
#ifndef CLASSES_BODY_ITEMS_H #ifndef CLASSES_BODY_ITEMS_H
#define CLASSES_BODY_ITEMS_H #define CLASSES_BODY_ITEMS_H
#include "base_struct.h"
class LIB_COMPONENT; class LIB_COMPONENT;
class PLOTTER; class PLOTTER;

View File

@ -48,51 +48,22 @@
#include "build_version.h" #include "build_version.h"
#include <set>
/** /**
* @bug - Every place in this file where fprintf() is used and the return * @bug - Every place in this file where fprintf() is used and the return
* is not checked is a bug. The fprintf() function can fail and * is not checked is a bug. The fprintf() function can fail and
* returns a value less than 0 when it does. * returns a value less than 0 when it does.
*/ */
static bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName );
static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f,
bool with_pcbnew );
static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f );
static void WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList );
static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f,
bool use_netnames );
static bool WriteGENERICListOfNetsTxt( FILE* f, NETLIST_OBJECT_LIST& aObjectsList );
static bool WriteGENERICListOfNets( wxXmlNode* aNode, NETLIST_OBJECT_LIST& aObjectsList );
static void AddPinToComponentPinList( SCH_COMPONENT* Component,
SCH_SHEET_PATH* sheet,
LIB_PIN* PinEntry );
static void FindAllInstancesOfComponent( SCH_COMPONENT* Component,
LIB_COMPONENT* aEntry,
SCH_SHEET_PATH* Sheet_in );
static bool SortPinsByNum( NETLIST_OBJECT* Pin1, NETLIST_OBJECT* Pin2 );
static void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList );
static NETLIST_OBJECT_LIST s_SortedComponentPinList;
#include <set>
/** /**
* Class UNIQUE_STRINGS * Class UNIQUE_STRINGS
* will keep track of unique wxStrings and is useful in telling if a string * tracks unique wxStrings and is useful in telling if a string
* has been seen before. * has been seen before.
*/ */
class UNIQUE_STRINGS class UNIQUE_STRINGS
{ {
private:
std::set<wxString> m_set; ///< set of wxStrings already found std::set<wxString> m_set; ///< set of wxStrings already found
public: public:
@ -119,8 +90,77 @@ bool UNIQUE_STRINGS::Lookup( const wxString& aString )
return ret; return ret;
} }
/// Used for multi part per package components, avoids using a component more than once.
static UNIQUE_STRINGS s_ReferencesAlreadyFound; /**
* Class EXPORT_HELP
* is a private implementation class used in this source file to keep track
* of and recycle datastructures used in the generation of various exported netlist
* files. Since it is private it is not in a header file.
*/
class EXPORT_HELP
{
NETLIST_OBJECT_LIST m_SortedComponentPinList;
/// Used for "multi parts per package" components, avoids processing a lib component more than once.
UNIQUE_STRINGS m_ReferencesAlreadyFound;
/**
* Function sprintPinNetName
* formats the net name for \a aPin using \a aNetNameFormat into \a aResult.
* <p>
* Net name is:
* <ul>
* <li> "?" if pin not connected
* <li> "netname" for global net (like gnd, vcc ..
* <li> "netname_sheetnumber" for the usual nets
* </ul>
*/
static void sprintPinNetName( wxString* aResult, const wxString& aNetNameFormat, NETLIST_OBJECT* aPin );
/**
* Function findNextComponentAndCreatePinList
* finds a "suitable" component from the DrawList and optionally builds
* its pin list int m_SortedComponentPinList. The list is sorted by pin num.
* A suitable component is a "new" real component (power symbols are not
* considered).
*/
SCH_COMPONENT* findNextComponentAndCreatPinList( EDA_BaseStruct* aItem,
SCH_SHEET_PATH* aSheetPath );
public:
bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName );
/**
* Function WriteNetListPCBNEW
* generates a net list file (Format 2 improves ORCAD PCB)
* = TRUE if with_pcbnew
* Format Pcbnew (OrcadPcb2 + reviews and lists of net)
* = FALSE if with_pcbnew
* Format ORCADPCB2 strict
*/
bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f,
bool with_pcbnew );
void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f );
void WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList );
void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f,
bool use_netnames );
bool WriteGENERICListOfNetsTxt( FILE* f, NETLIST_OBJECT_LIST& aObjectsList );
bool WriteGENERICListOfNets( wxXmlNode* aNode, NETLIST_OBJECT_LIST& aObjectsList );
bool AddPinToComponentPinList( SCH_COMPONENT* Component,
SCH_SHEET_PATH* sheet,
LIB_PIN* PinEntry );
void FindAllInstancesOfComponent( SCH_COMPONENT* Component,
LIB_COMPONENT* aEntry,
SCH_SHEET_PATH* Sheet_in );
void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList );
};
/** /**
@ -136,8 +176,9 @@ static UNIQUE_STRINGS s_ReferencesAlreadyFound;
bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFullFileName, bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFullFileName,
bool aUse_netnames ) bool aUse_netnames )
{ {
bool ret = true; bool ret = true;
FILE* f = NULL; FILE* f = NULL;
EXPORT_HELP helper;
if( aFormat < NET_TYPE_CUSTOM1 ) if( aFormat < NET_TYPE_CUSTOM1 )
{ {
@ -154,22 +195,22 @@ bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFull
switch( aFormat ) switch( aFormat )
{ {
case NET_TYPE_PCBNEW: case NET_TYPE_PCBNEW:
ret = WriteNetListPCBNEW( this, f, TRUE ); ret = helper.WriteNetListPCBNEW( this, f, TRUE );
fclose( f ); fclose( f );
break; break;
case NET_TYPE_ORCADPCB2: case NET_TYPE_ORCADPCB2:
ret = WriteNetListPCBNEW( this, f, FALSE ); ret = helper.WriteNetListPCBNEW( this, f, FALSE );
fclose( f ); fclose( f );
break; break;
case NET_TYPE_CADSTAR: case NET_TYPE_CADSTAR:
WriteNetListCADSTAR( this, f ); helper.WriteNetListCADSTAR( this, f );
fclose( f ); fclose( f );
break; break;
case NET_TYPE_SPICE: case NET_TYPE_SPICE:
WriteNetListPspice( this, f, aUse_netnames ); helper.WriteNetListPspice( this, f, aUse_netnames );
fclose( f ); fclose( f );
break; break;
@ -178,7 +219,7 @@ bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFull
wxFileName tmpFile = aFullFileName; wxFileName tmpFile = aFullFileName;
tmpFile.SetExt( wxT( "tmp" ) ); tmpFile.SetExt( wxT( "tmp" ) );
ret = Write_GENERIC_NetList( this, tmpFile.GetFullPath() ); ret = helper.Write_GENERIC_NetList( this, tmpFile.GetFullPath() );
if( !ret ) if( !ret )
break; break;
@ -210,31 +251,76 @@ bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFull
} }
/* Find a "suitable" component from the DrawList /*
* build its pin list s_SortedComponentPinList. * Comparison routine for sorting by pin numbers.
* The list is sorted by pin num
* A suitable component is a "new" real component (power symbols are not
* considered)
* Must be deallocated by the user
*/ */
static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* item, static bool sortPinsByNum( NETLIST_OBJECT* Pin1, NETLIST_OBJECT* Pin2 )
SCH_SHEET_PATH* path )
{ {
s_SortedComponentPinList.clear(); // return "lhs < rhs"
return RefDesStringCompare( Pin1->GetPinNumText(), Pin2->GetPinNumText() ) < 0;
}
// continue searching from the middle of a linked list
for( ; item; item = item->Next() ) void EXPORT_HELP::sprintPinNetName( wxString* aResult,
const wxString& aNetNameFormat, NETLIST_OBJECT* aPin )
{
int netcode = aPin->GetNet();
// Not wxString::Clear(), which would free memory. We want the worst
// case wxString memory to grow to avoid reallocation from within the
// caller's loop.
aResult->Empty();
if( netcode != 0 && aPin->m_FlagOfConnection == PAD_CONNECT )
{ {
if( item->Type() != TYPE_SCH_COMPONENT ) NETLIST_OBJECT* netref = aPin->m_NetNameCandidate;
if( netref )
*aResult = netref->m_Label;
if( !aResult->IsEmpty() )
{
// prefix non global label names with the sheet path, to avoid name collisions
if( netref->m_Type != NET_PINLABEL && netref->m_Type != NET_GLOBLABEL )
{
wxString lnet = *aResult;
*aResult = netref->m_SheetList.PathHumanReadable();
// If sheet path is too long, use the time stamp name instead
if( aResult->Length() > 32 )
*aResult = netref->m_SheetList.Path();
*aResult += lnet;
}
}
else
{
aResult->Printf( aNetNameFormat.GetData(), netcode );
}
}
}
SCH_COMPONENT* EXPORT_HELP::findNextComponentAndCreatPinList( EDA_BaseStruct* aItem,
SCH_SHEET_PATH* aSheetPath )
{
wxString ref;
m_SortedComponentPinList.clear();
// continue searching from the middle of a linked list (the draw list)
for( ; aItem; aItem = aItem->Next() )
{
if( aItem->Type() != TYPE_SCH_COMPONENT )
continue; continue;
// found next component // found next component
SCH_COMPONENT* comp = (SCH_COMPONENT*) item; SCH_COMPONENT* comp = (SCH_COMPONENT*) aItem;
// Power symbols and other components which have the reference starting // Power symbols and other components which have the reference starting
// with "#" are not included in netlist (pseudo or virtual components) // with "#" are not included in netlist (pseudo or virtual components)
wxString ref = comp->GetRef( path ); ref = comp->GetRef( aSheetPath );
if( ref[0] == wxChar( '#' ) ) // ignore it if( ref[0] == wxChar( '#' ) )
continue; continue;
// if( Component->m_FlagControlMulti == 1 ) // if( Component->m_FlagControlMulti == 1 )
@ -247,22 +333,23 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* item,
if( !entry ) if( !entry )
continue; continue;
// If Multi parts per package // If component is a "multi parts per package" type
if( entry->GetPartCount() > 1 ) if( entry->GetPartCount() > 1 )
{ {
// test if already visited, and if so skip // test if already visited, and if so skip
if( s_ReferencesAlreadyFound.Lookup( ref ) ) if( m_ReferencesAlreadyFound.Lookup( ref ) )
continue; continue;
// Collect all parts and pins for this first occurance of reference // Collect all parts and pins for this first occurance of reference.
FindAllInstancesOfComponent( comp, entry, path ); // This is only done once, it would be too expensive otherwise.
FindAllInstancesOfComponent( comp, entry, aSheetPath );
} }
else // entry->GetPartCount() <= 1 means one part per package else // entry->GetPartCount() <= 1 means one part per package
{ {
LIB_PIN_LIST pins; LIB_PIN_LIST pins; // constructed once here
entry->GetPins( pins, comp->GetUnitSelection( path ), comp->m_Convert ); entry->GetPins( pins, comp->GetUnitSelection( aSheetPath ), comp->m_Convert );
for( size_t i = 0; i < pins.size(); i++ ) for( size_t i = 0; i < pins.size(); i++ )
{ {
@ -270,16 +357,16 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* item,
wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE ); wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE );
AddPinToComponentPinList( comp, path, pin ); AddPinToComponentPinList( comp, aSheetPath, pin );
} }
} }
// Sort pins in s_SortedComponentPinList by pin number // Sort pins in m_SortedComponentPinList by pin number
sort( s_SortedComponentPinList.begin(), sort( m_SortedComponentPinList.begin(),
s_SortedComponentPinList.end(), SortPinsByNum ); m_SortedComponentPinList.end(), sortPinsByNum );
// Remove duplicate Pins in s_SortedComponentPinList // Remove duplicate Pins in m_SortedComponentPinList
EraseDuplicatePins( s_SortedComponentPinList ); EraseDuplicatePins( m_SortedComponentPinList );
return comp; return comp;
} }
@ -288,48 +375,6 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* item,
} }
/* Return the net name for the pin Pin.
* Net name is:
* "?" if pin not connected
* "netname" for global net (like gnd, vcc ..
* "netname_sheetnumber" for the usual nets
*/
static wxString ReturnPinNetName( NETLIST_OBJECT* Pin, const wxString& DefaultFormatNetname )
{
int netcode = Pin->GetNet();
wxString NetName;
if( ( netcode == 0 ) || ( Pin->m_FlagOfConnection != PAD_CONNECT ) )
return NetName;
NETLIST_OBJECT* netref = Pin->m_NetNameCandidate;
if( netref )
NetName = netref->m_Label;
if( !NetName.IsEmpty() )
{
// prefix non global labels names by the sheet path, to avoid names collisions
if( ( netref->m_Type != NET_PINLABEL )
&& ( netref->m_Type != NET_GLOBLABEL ) )
{
wxString lnet = NetName;
NetName = netref->m_SheetList.PathHumanReadable();
// If sheet path is too long, use the time stamp name instead
if( NetName.Length() > 32 )
NetName = netref->m_SheetList.Path();
NetName += lnet;
}
}
else
{
NetName.Printf( DefaultFormatNetname.GetData(), netcode );
}
return NetName;
}
/** /**
* Function Node * Function Node
* is a convenience function that creates a new wxXmlNode with an optional textual child. * is a convenience function that creates a new wxXmlNode with an optional textual child.
@ -353,7 +398,7 @@ static wxXmlNode* Node( const wxString& aName, const wxString& aTextualContent =
* creates a generic netlist, now in XML. * creates a generic netlist, now in XML.
* @return bool - true if there were no errors, else false. * @return bool - true if there were no errors, else false.
*/ */
bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName ) bool EXPORT_HELP::Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName )
{ {
#if 1 #if 1
// output the XML format netlist. // output the XML format netlist.
@ -391,7 +436,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi
const wxString sPart = wxT( "part" ); const wxString sPart = wxT( "part" );
const wxString sNames = wxT( "names" ); const wxString sNames = wxT( "names" );
s_ReferencesAlreadyFound.Clear(); m_ReferencesAlreadyFound.Clear();
xdoc.SetRoot( xroot = Node( wxT( "netlist" ) ) ); xdoc.SetRoot( xroot = Node( wxT( "netlist" ) ) );
xroot->AddProperty( wxT( "version" ), wxT( "B" ) ); xroot->AddProperty( wxT( "version" ), wxT( "B" ) );
@ -406,7 +451,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi
{ {
for( EDA_BaseStruct* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() ) for( EDA_BaseStruct* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() )
{ {
SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( schItem, path ); SCH_COMPONENT* comp = findNextComponentAndCreatPinList( schItem, path );
if( !comp ) if( !comp )
break; // No component left break; // No component left
@ -497,7 +542,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi
return false; return false;
} }
s_ReferencesAlreadyFound.Clear(); m_ReferencesAlreadyFound.Clear();
ret |= fprintf( out, "$BeginNetlist\n" ); ret |= fprintf( out, "$BeginNetlist\n" );
@ -510,7 +555,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi
{ {
for( EDA_BaseStruct* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() ) for( EDA_BaseStruct* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() )
{ {
SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( schItem, path ); SCH_COMPONENT* comp = findNextComponentAndCreatPinList( schItem, path );
if( !comp ) if( !comp )
break; // No component left break; // No component left
@ -541,9 +586,9 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi
// Write pin list: // Write pin list:
ret |= fprintf( out, "$BeginPinList\n" ); ret |= fprintf( out, "$BeginPinList\n" );
for( unsigned ii = 0; ii < s_SortedComponentPinList.size(); ii++ ) for( unsigned ii = 0; ii < m_SortedComponentPinList.size(); ii++ )
{ {
NETLIST_OBJECT* Pin = s_SortedComponentPinList[ii]; NETLIST_OBJECT* Pin = m_SortedComponentPinList[ii];
if( !Pin ) if( !Pin )
continue; continue;
@ -586,7 +631,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi
* [.-] Or PSpice gnucap are beginning * [.-] Or PSpice gnucap are beginning
* + + Gnucap and PSpice are ultimately NetList * + + Gnucap and PSpice are ultimately NetList
*/ */
static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_netnames ) void EXPORT_HELP::WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_netnames )
{ {
char Line[1024]; char Line[1024];
SCH_SHEET_PATH* sheet; SCH_SHEET_PATH* sheet;
@ -596,6 +641,7 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_
wxString text; wxString text;
wxArrayString SpiceCommandAtBeginFile, SpiceCommandAtEndFile; wxArrayString SpiceCommandAtBeginFile, SpiceCommandAtEndFile;
wxString msg; wxString msg;
wxString netName;
#define BUFYPOS_LEN 4 #define BUFYPOS_LEN 4
wxChar bufnum[BUFYPOS_LEN + 1]; wxChar bufnum[BUFYPOS_LEN + 1];
@ -623,12 +669,15 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_
wxChar ident; wxChar ident;
if( DrawList->Type() != TYPE_SCH_TEXT ) if( DrawList->Type() != TYPE_SCH_TEXT )
continue; continue;
#define DRAWTEXT ( (SCH_TEXT*) DrawList ) #define DRAWTEXT ( (SCH_TEXT*) DrawList )
text = DRAWTEXT->m_Text; if( text.IsEmpty() ) text = DRAWTEXT->m_Text; if( text.IsEmpty() )
continue; continue;
ident = text.GetChar( 0 ); ident = text.GetChar( 0 );
if( ident != '.' && ident != '-' && ident != '+' ) if( ident != '.' && ident != '-' && ident != '+' )
continue; continue;
text.Remove( 0, 1 ); // Remove the first char. text.Remove( 0, 1 ); // Remove the first char.
text.Remove( 6 ); // text contains 6 char. text.Remove( 6 ); // text contains 6 char.
text.MakeLower(); text.MakeLower();
@ -673,34 +722,37 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_
// Create component list // Create component list
s_ReferencesAlreadyFound.Clear(); m_ReferencesAlreadyFound.Clear();
for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
{ {
for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() ) for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() )
{ {
DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet ); DrawList = Component = findNextComponentAndCreatPinList( DrawList, sheet );
if( Component == NULL ) if( Component == NULL )
break; break;
fprintf( f, "%s ", CONV_TO_UTF8( Component->GetRef( sheet ) ) ); fprintf( f, "%s ", CONV_TO_UTF8( Component->GetRef( sheet ) ) );
// Write pin list: // Write pin list:
for( unsigned ii = 0; ii < s_SortedComponentPinList.size(); ii++ ) for( unsigned ii = 0; ii < m_SortedComponentPinList.size(); ii++ )
{ {
NETLIST_OBJECT* Pin = s_SortedComponentPinList[ii]; NETLIST_OBJECT* Pin = m_SortedComponentPinList[ii];
if( !Pin ) if( !Pin )
continue; continue;
wxString NetName = ReturnPinNetName( Pin, wxT( "N-%.6d" ) );
if( NetName.IsEmpty() ) sprintPinNetName( &netName , wxT( "N-%.6d" ), Pin );
NetName = wxT( "?" );
if( netName.IsEmpty() )
netName = wxT( "?" );
if( use_netnames ) if( use_netnames )
fprintf( f, " %s", CONV_TO_UTF8( NetName ) ); fprintf( f, " %s", CONV_TO_UTF8( netName ) );
else // Use number for net names (with net number = 0 for else // Use number for net names (with net number = 0 for
// "GND" // "GND"
{ {
// NetName = "0" is "GND" net for Spice // NetName = "0" is "GND" net for Spice
if( NetName == wxT( "0" ) || NetName == wxT( "GND" ) ) if( netName == wxT( "0" ) || netName == wxT( "GND" ) )
fprintf( f, " 0" ); fprintf( f, " 0" );
else else
fprintf( f, " %d", Pin->GetNet() ); fprintf( f, " %d", Pin->GetNet() );
@ -712,7 +764,7 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_
} }
} }
s_SortedComponentPinList.clear(); m_SortedComponentPinList.clear();
/* Print texts starting by [+]pspice , ou [+]gnucap */ /* Print texts starting by [+]pspice , ou [+]gnucap */
nbitems = SpiceCommandAtEndFile.GetCount(); nbitems = SpiceCommandAtEndFile.GetCount();
@ -733,18 +785,13 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_
} }
/* Generate net list file (Format 2 improves ORCAD PCB) bool EXPORT_HELP::WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with_pcbnew )
* = TRUE if with_pcbnew
* Format Pcbnew (OrcadPcb2 + reviews and lists of net)
* = FALSE if with_pcbnew
* Format ORCADPCB2 strict
*/
static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with_pcbnew )
{ {
wxString field; wxString field;
wxString footprint; wxString footprint;
char dateBuf[256]; char dateBuf[256];
int ret = 0; // zero now, OR in the sign bit on error int ret = 0; // zero now, OR in the sign bit on error
wxString netName;
std::vector<OBJ_CMP_TO_LIST> cmpList; std::vector<OBJ_CMP_TO_LIST> cmpList;
@ -757,7 +804,7 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
// Create netlist module section // Create netlist module section
s_ReferencesAlreadyFound.Clear(); m_ReferencesAlreadyFound.Clear();
SCH_SHEET_LIST sheetList; SCH_SHEET_LIST sheetList;
@ -765,7 +812,7 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
{ {
for( EDA_BaseStruct* item = path->LastDrawList(); item; item = item->Next() ) for( EDA_BaseStruct* item = path->LastDrawList(); item; item = item->Next() )
{ {
SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( item, path ); SCH_COMPONENT* comp = findNextComponentAndCreatPinList( item, path );
if( !comp ) if( !comp )
break; break;
@ -816,20 +863,20 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
ret |= fprintf( f, "\n" ); ret |= fprintf( f, "\n" );
// Write pin list: // Write pin list:
for( unsigned ii = 0; ii < s_SortedComponentPinList.size(); ii++ ) for( unsigned ii = 0; ii < m_SortedComponentPinList.size(); ii++ )
{ {
NETLIST_OBJECT* pin = s_SortedComponentPinList[ii]; NETLIST_OBJECT* pin = m_SortedComponentPinList[ii];
if( !pin ) if( !pin )
continue; continue;
wxString netname = ReturnPinNetName( pin, wxT( "N-%.6d" ) ); sprintPinNetName( &netName, wxT( "N-%.6d" ), pin );
if( netname.IsEmpty() ) if( netName.IsEmpty() )
netname = wxT( "?" ); netName = wxT( "?" );
netname.Replace( wxT( " " ), wxT( "_" ) ); netName.Replace( wxT( " " ), wxT( "_" ) );
ret |= fprintf( f, " ( %4.4s %s )\n", (char*) &pin->m_PinNum, ret |= fprintf( f, " ( %4.4s %s )\n", (char*) &pin->m_PinNum,
CONV_TO_UTF8( netname ) ); CONV_TO_UTF8( netName ) );
} }
ret |= fprintf( f, " )\n" ); ret |= fprintf( f, " )\n" );
@ -838,7 +885,7 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
ret |= fprintf( f, ")\n*\n" ); ret |= fprintf( f, ")\n*\n" );
s_SortedComponentPinList.clear(); m_SortedComponentPinList.clear();
// Write the allowed footprint list for each component // Write the allowed footprint list for each component
if( with_pcbnew && cmpList.size() ) if( with_pcbnew && cmpList.size() )
@ -887,34 +934,43 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
/* /*
* Add a new pin description in the pin list s_SortedComponentPinList * Add a new pin description in the pin list m_SortedComponentPinList
* a pin description is a pointer to the corresponding structure * a pin description is a pointer to the corresponding structure
* created by BuildNetList() in the table g_NetObjectslist * created by BuildNetList() in the table g_NetObjectslist
*/ */
static void AddPinToComponentPinList( SCH_COMPONENT* Component, bool EXPORT_HELP::AddPinToComponentPinList( SCH_COMPONENT* aComponent,
SCH_SHEET_PATH* sheetlist, LIB_PIN* Pin ) SCH_SHEET_PATH* aSheetPath, LIB_PIN* aPin )
{ {
// Search the PIN description for Pin in g_NetObjectslist // Search the PIN description for Pin in g_NetObjectslist
for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ ) for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ )
{ {
if( g_NetObjectslist[ii]->m_Type != NET_PIN ) NETLIST_OBJECT* pin = g_NetObjectslist[ii];
continue;
if( g_NetObjectslist[ii]->m_Link != Component ) if( pin->m_Type != NET_PIN )
continue;
if( g_NetObjectslist[ii]->m_SheetList != *sheetlist )
continue;
if( g_NetObjectslist[ii]->m_PinNum != Pin->m_PinNum )
continue; continue;
s_SortedComponentPinList.push_back( g_NetObjectslist[ii] ); if( pin->m_Link != aComponent )
continue;
if( s_SortedComponentPinList.size() >= MAXPIN ) if( pin->m_PinNum != aPin->m_PinNum )
continue;
// most expensive test at the end.
if( pin->m_SheetList != *aSheetPath )
continue;
m_SortedComponentPinList.push_back( pin );
if( m_SortedComponentPinList.size() >= MAXPIN )
{ {
// Log message for Internal error // Log message for Internal error
DisplayError( NULL, wxT( "AddPinToComponentPinList err: MAXPIN reached" ) ); DisplayError( NULL, wxT( "AddPinToComponentPinList err: MAXPIN reached" ) );
return;
} }
return true; // we're done, we appended.
} }
return false;
} }
@ -932,7 +988,7 @@ static void AddPinToComponentPinList( SCH_COMPONENT* Component,
* given component. * given component.
* Note: this list *MUST* be sorted by pin number (.m_PinNum member value) * Note: this list *MUST* be sorted by pin number (.m_PinNum member value)
*/ */
static void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList ) void EXPORT_HELP::EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList )
{ {
if( aPinList.size() == 0 ) // Trivial case: component with no pin if( aPinList.size() == 0 ) // Trivial case: component with no pin
return; return;
@ -959,6 +1015,7 @@ static void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList )
// other pin num end of duplicate list. // other pin num end of duplicate list.
if( aPinList[idxref]->m_PinNum != aPinList[jj]->m_PinNum ) if( aPinList[idxref]->m_PinNum != aPinList[jj]->m_PinNum )
break; break;
if( aPinList[idxref]->m_FlagOfConnection == PAD_CONNECT ) if( aPinList[idxref]->m_FlagOfConnection == PAD_CONNECT )
aPinList[jj] = NULL; aPinList[jj] = NULL;
else /* the reference pin is not connected: remove this pin if the else /* the reference pin is not connected: remove this pin if the
@ -980,81 +1037,59 @@ static void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList )
/** /**
* Function FindAllInstancesOfComponent * Function FindAllInstancesOfComponent
* is used for multiple parts per package components. * is used for "multiple parts per package" components.
* *
* Search all instances of Component_in, * Search all instances of Component_in,
* Calls AddPinToComponentPinList() to and pins founds to the current * Calls AddPinToComponentPinList() to and pins founds to the current
* component pin list * component pin list
*/ */
static void FindAllInstancesOfComponent( SCH_COMPONENT* Component_in, void EXPORT_HELP::FindAllInstancesOfComponent( SCH_COMPONENT* aComponent,
LIB_COMPONENT* aEntry, LIB_COMPONENT* aEntry,
SCH_SHEET_PATH* Sheet_in ) SCH_SHEET_PATH* aSheetPath )
{ {
EDA_BaseStruct* SchItem; wxString ref = aComponent->GetRef( aSheetPath );
SCH_COMPONENT* Component2; wxString ref2;
LIB_PIN* pin;
SCH_SHEET_PATH* sheet;
wxString str, Reference = Component_in->GetRef( Sheet_in );
SCH_SHEET_LIST SheetList; SCH_SHEET_LIST sheetList;
for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) for( SCH_SHEET_PATH* sheet = sheetList.GetFirst(); sheet; sheet = sheetList.GetNext() )
{ {
for( SchItem = sheet->LastDrawList(); SchItem; SchItem = SchItem->Next() ) for( EDA_BaseStruct* schItem = sheet->LastDrawList(); schItem; schItem = schItem->Next() )
{ {
if( SchItem->Type() != TYPE_SCH_COMPONENT ) if( schItem->Type() != TYPE_SCH_COMPONENT )
continue; continue;
Component2 = (SCH_COMPONENT*) SchItem; SCH_COMPONENT* comp2 = (SCH_COMPONENT*) schItem;
str = Component2->GetRef( sheet ); ref2 = comp2->GetRef( sheet );
if( str.CmpNoCase( Reference ) != 0 ) if( ref2.CmpNoCase( ref ) != 0 )
continue; continue;
if( aEntry == NULL ) if( aEntry == NULL )
continue; continue;
for( pin = aEntry->GetNextPin(); pin != NULL; pin = aEntry->GetNextPin( pin ) ) for( LIB_PIN* pin = aEntry->GetNextPin(); pin; pin = aEntry->GetNextPin( pin ) )
{ {
wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE ); wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE );
if( pin->m_Unit if( pin->m_Unit && pin->m_Unit != comp2->GetUnitSelection( aSheetPath ) )
&& ( pin->m_Unit != Component2->GetUnitSelection( sheet ) ) )
continue; continue;
if( pin->m_Convert if( pin->m_Convert && pin->m_Convert != comp2->m_Convert )
&& ( pin->m_Convert != Component2->m_Convert ) )
continue; continue;
// A suitable pin in found: add it to the current list // A suitable pin is found: add it to the current list
AddPinToComponentPinList( Component2, sheet, pin ); AddPinToComponentPinList( comp2, sheet, pin );
} }
} }
} }
} }
/*
* Comparison routine for sorting by pin numbers.
*/
static bool SortPinsByNum( NETLIST_OBJECT* Pin1, NETLIST_OBJECT* Pin2 )
{
int Num1, Num2;
char Line[5];
Num1 = Pin1->m_PinNum;
Num2 = Pin2->m_PinNum;
Line[4] = 0;
memcpy( Line, &Num1, 4 ); Num1 = atoi( Line );
memcpy( Line, &Num2, 4 ); Num2 = atoi( Line );
return Num1 < Num2;
}
/* Written in the file / net list (ranked by Netcode), and elements that are /* Written in the file / net list (ranked by Netcode), and elements that are
* connected * connected
*/ */
static bool WriteGENERICListOfNetsTxt( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) bool EXPORT_HELP::WriteGENERICListOfNetsTxt( FILE* f, NETLIST_OBJECT_LIST& aObjectsList )
{ {
int ret = 0; int ret = 0;
int netCode; int netCode;
@ -1144,7 +1179,7 @@ static bool WriteGENERICListOfNetsTxt( FILE* f, NETLIST_OBJECT_LIST& aObjectsLis
* Function WriteGENERICListOfNets * Function WriteGENERICListOfNets
* saves a netlist in xml format. * saves a netlist in xml format.
*/ */
static bool WriteGENERICListOfNets( wxXmlNode* aNode, NETLIST_OBJECT_LIST& aObjectsList ) bool EXPORT_HELP::WriteGENERICListOfNets( wxXmlNode* aNode, NETLIST_OBJECT_LIST& aObjectsList )
{ {
wxString netCodeTxt; wxString netCodeTxt;
wxString netName; wxString netName;
@ -1158,7 +1193,7 @@ static bool WriteGENERICListOfNets( wxXmlNode* aNode, NETLIST_OBJECT_LIST& aObje
wxString sNode = wxT( "node" ); wxString sNode = wxT( "node" );
wxString sFmtd = wxT( "%d" ); wxString sFmtd = wxT( "%d" );
wxXmlNode* xnet; wxXmlNode* xnet = 0;
int netCode; int netCode;
int lastNetCode = -1; int lastNetCode = -1;
int sameNetcodeCount = 0; int sameNetcodeCount = 0;
@ -1255,7 +1290,7 @@ wxString StartLine( wxT( "." ) );
* .. B * T3 1 * .. B * T3 1
*U1 * 14 *U1 * 14
*/ */
static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ) void EXPORT_HELP::WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
{ {
wxString StartCmpDesc = StartLine + wxT( "ADD_COM" ); wxString StartCmpDesc = StartLine + wxT( "ADD_COM" );
wxString msg; wxString msg;
@ -1274,7 +1309,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
fprintf( f, "\n" ); fprintf( f, "\n" );
// Create netlist module section // Create netlist module section
s_ReferencesAlreadyFound.Clear(); m_ReferencesAlreadyFound.Clear();
SCH_SHEET_LIST SheetList; SCH_SHEET_LIST SheetList;
@ -1282,7 +1317,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
{ {
for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() ) for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() )
{ {
DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet ); DrawList = Component = findNextComponentAndCreatPinList( DrawList, sheet );
if( Component == NULL ) if( Component == NULL )
break; break;
@ -1310,7 +1345,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
fprintf( f, "\n" ); fprintf( f, "\n" );
s_SortedComponentPinList.clear(); m_SortedComponentPinList.clear();
WriteListOfNetsCADSTAR( f, g_NetObjectslist ); WriteListOfNetsCADSTAR( f, g_NetObjectslist );
@ -1326,7 +1361,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
*. B U1 100 *. B U1 100
* 6 CA * 6 CA
*/ */
static void WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) void EXPORT_HELP::WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList )
{ {
wxString InitNetDesc = StartLine + wxT( "ADD_TER" ); wxString InitNetDesc = StartLine + wxT( "ADD_TER" );
wxString StartNetDesc = StartLine + wxT( "TER" ); wxString StartNetDesc = StartLine + wxT( "TER" );

View File

@ -273,7 +273,7 @@ void WinEDA_SchematicFrame::BuildNetListBase()
sort( g_NetObjectslist.begin(), g_NetObjectslist.end(), SortItemsbyNetcode ); sort( g_NetObjectslist.begin(), g_NetObjectslist.end(), SortItemsbyNetcode );
#if defined(NETLIST_DEBUG) && defined(DEBUG) #if defined(NETLIST_DEBUG) && defined(DEBUG)
std::cout << "after qsort()\n"; std::cout << "\n\nafter qsort()\n";
dumpNetTable(); dumpNetTable();
#endif #endif
@ -467,7 +467,6 @@ static void AddConnectedObjects( SCH_SHEET_PATH* sheetlist,
NETLIST_OBJECT* new_item; NETLIST_OBJECT* new_item;
SCH_COMPONENT* DrawLibItem; SCH_COMPONENT* DrawLibItem;
LIB_COMPONENT* Entry; LIB_COMPONENT* Entry;
LIB_PIN* pin;
SCH_SHEET_PATH list; SCH_SHEET_PATH list;
DrawList = sheetlist->LastScreen()->EEDrawList; DrawList = sheetlist->LastScreen()->EEDrawList;
@ -587,24 +586,20 @@ static void AddConnectedObjects( SCH_SHEET_PATH* sheetlist,
case TYPE_SCH_COMPONENT: case TYPE_SCH_COMPONENT:
DrawLibItem = (SCH_COMPONENT*) DrawList; DrawLibItem = (SCH_COMPONENT*) DrawList;
Entry = Entry = CMP_LIBRARY::FindLibraryComponent( DrawLibItem->m_ChipName );
CMP_LIBRARY::FindLibraryComponent( DrawLibItem->m_ChipName );
if( Entry == NULL ) if( Entry == NULL )
break; break;
for( pin = Entry->GetNextPin(); pin != NULL; for( LIB_PIN* pin = Entry->GetNextPin(); pin; pin = Entry->GetNextPin( pin ) )
pin = Entry->GetNextPin( pin ) )
{ {
wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE ); wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE );
if( pin->m_Unit if( pin->m_Unit &&
&& ( pin->m_Unit != ( pin->m_Unit != DrawLibItem->GetUnitSelection( sheetlist ) ) )
DrawLibItem->GetUnitSelection( sheetlist ) ) )
continue; continue;
if( pin->m_Convert if( pin->m_Convert &&
&& ( pin->m_Convert != DrawLibItem->m_Convert ) ) ( pin->m_Convert != DrawLibItem->m_Convert ) )
continue; continue;
wxPoint pos2 = wxPoint pos2 =
@ -640,7 +635,6 @@ static void AddConnectedObjects( SCH_SHEET_PATH* sheetlist,
aNetItemBuffer.push_back( new_item ); aNetItemBuffer.push_back( new_item );
} }
} }
break; break;
case DRAW_POLYLINE_STRUCT_TYPE: case DRAW_POLYLINE_STRUCT_TYPE:

View File

@ -382,4 +382,4 @@ void MyFree( void* pt_mem );
void* MyZMalloc( size_t nb_octets ); void* MyZMalloc( size_t nb_octets );
void* MyMalloc( size_t nb_octets ); void* MyMalloc( size_t nb_octets );
#endif /* __INCLUDE__COMMON_H__ */ #endif // __INCLUDE__COMMON_H__

View File

@ -79,5 +79,27 @@ bool WildCompareString( const wxString& pattern,
*/ */
char* to_point( char* Text ); char* to_point( char* Text );
/**
* Function RefDesStringCompare
* acts just like the strcmp function but treats numbers within the string text
* correctly for sorting. eg. A10 > A2
* return -1 if first string is less than the second
* return 0 if the strings are equal
* return 1 if the first string is greater than the second
*/
int RefDesStringCompare( const wxString& lhs, const wxString& rhs );
#endif /* __INCLUDE__KICAD_STRING_H__ */ /**
* Function SplitString
* breaks a string into three parts.
* The alphabetic preamble
* The numeric part
* Any alphabetic ending
* For example C10A is split to C 10 A
*/
int SplitString( wxString strToSplit,
wxString* strBeginning,
wxString* strDigits,
wxString* strEnd );
#endif // __INCLUDE__KICAD_STRING_H__

View File

@ -16,20 +16,22 @@
/** /**
* Function GetChars * Function GetChars
* returns a pointer to the actual character data, either 8 or * returns a wxChar* to the actual character data within a wxString, and is
* 16 bits wide, depending on how the wxWidgets library was compiled. * helpful for passing strings to wxString::Printf(wxT("%s"), GetChars(wxString) )
* <p>
* wxChar is defined to be <ul>
* <li> standard C style char when wxUSE_UNICODE==0 </li>
* <li> wchar_t when wxUSE_UNICODE==1 (the default). </li>
* <ul>
* i.e. it depends on how the wxWidgets library was compiled. There was a period
* during the development of wxWidgets 2.9 when GetData() was missing, so this
* function was used to provide insulation from that design change. It may
* no longer be needed, and is harmless. GetData() seems to be an acceptable
* alternative in all cases now.
*/ */
static inline const wxChar* GetChars( wxString s ) static inline const wxChar* GetChars( const wxString& s )
{ {
#if wxCHECK_VERSION( 2, 9, 0 ) #if wxCHECK_VERSION( 2, 9, 0 )
/* To be Fixed:
* Currently, access to the actual character data in <wxString::Printf
* is a moving target
* So, with wxWidgets 2.9.0 this line is subject to change:
*/
// return (const wxChar*) s.wx_str();
return (const wxChar*) s.c_str(); return (const wxChar*) s.c_str();
#else #else
return s.GetData(); return s.GetData();