Put netform.cpp functions into a class so scratch memory objects can be freed.

Improve code performance and appearance
This commit is contained in:
Dick Hollenbeck 2010-08-02 21:13:33 -05:00
commit 5d7410c9ea
14 changed files with 462 additions and 359 deletions

View File

@ -320,3 +320,113 @@ char* strupper( char* 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 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
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
* editing sheet parameters)
*/
wxString SCH_SHEET_PATH::PathHumanReadable()
wxString SCH_SHEET_PATH::PathHumanReadable() const
{
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 )
{
m_numSheets = d1.m_numSheets;
unsigned 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 )
return false;
for( unsigned i = 0; i < m_numSheets; i++ )
{
if( m_sheets[i] != d1.m_sheets[i] )
@ -384,15 +386,24 @@ 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 )
return true;
for( unsigned i = 0; i < m_numSheets; 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 false;
}

View File

@ -150,7 +150,7 @@ public:
* stamps in the path. (Time stamps do not change even when editing
* sheet parameters).
*/
wxString PathHumanReadable();
wxString PathHumanReadable() const;
/** Function BuildSheetPathInfoFromSheetPathValue
* 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 ) 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"
#if defined(DEBUG)
#include <iostream>
const char* ShowType( NetObjetType aType )
@ -134,3 +133,4 @@ NETLIST_OBJECT::NETLIST_OBJECT( NETLIST_OBJECT& aSource )
NETLIST_OBJECT::~NETLIST_OBJECT()
{
}

View File

@ -6,6 +6,9 @@
#ifndef _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...) */
enum NetObjetType {
NET_ITEM_UNSPECIFIED, // only for not yet initialized instances
@ -105,6 +108,17 @@ public:
void SetNet( int aNetCode ) { m_NetCode = aNetCode; }
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_

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()
* fill the buffer with pin num as a wxString
* Pin num is coded as a long

View File

@ -7,6 +7,7 @@
#ifndef 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
* pins */
@ -159,7 +160,12 @@ public:
*/
void ReturnPinStringNum( wxString& aStringBuffer ) const;
wxString GetNumber();
wxString GetNumber()
{
return ReturnPinStringNum( m_PinNum );
}
/** Function ReturnPinStringNum (static function)
* Pin num is coded as a long or 4 ascii chars

View File

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

View File

@ -48,51 +48,22 @@
#include "build_version.h"
#include <set>
/**
* @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
* 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
* 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.
*/
class UNIQUE_STRINGS
{
private:
std::set<wxString> m_set; ///< set of wxStrings already found
public:
@ -119,8 +90,77 @@ bool UNIQUE_STRINGS::Lookup( const wxString& aString )
return ret;
}
/// Used for multi part per package components, avoids using a component more than once.
static UNIQUE_STRINGS s_ReferencesAlreadyFound;
/**
* Class NETLIST_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 NETLIST_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 );
};
/**
@ -138,6 +178,7 @@ bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFull
{
bool ret = true;
FILE* f = NULL;
NETLIST_HELP helper;
if( aFormat < NET_TYPE_CUSTOM1 )
{
@ -154,22 +195,22 @@ bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFull
switch( aFormat )
{
case NET_TYPE_PCBNEW:
ret = WriteNetListPCBNEW( this, f, TRUE );
ret = helper.WriteNetListPCBNEW( this, f, TRUE );
fclose( f );
break;
case NET_TYPE_ORCADPCB2:
ret = WriteNetListPCBNEW( this, f, FALSE );
ret = helper.WriteNetListPCBNEW( this, f, FALSE );
fclose( f );
break;
case NET_TYPE_CADSTAR:
WriteNetListCADSTAR( this, f );
helper.WriteNetListCADSTAR( this, f );
fclose( f );
break;
case NET_TYPE_SPICE:
WriteNetListPspice( this, f, aUse_netnames );
helper.WriteNetListPspice( this, f, aUse_netnames );
fclose( f );
break;
@ -178,7 +219,7 @@ bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFull
wxFileName tmpFile = aFullFileName;
tmpFile.SetExt( wxT( "tmp" ) );
ret = Write_GENERIC_NetList( this, tmpFile.GetFullPath() );
ret = helper.Write_GENERIC_NetList( this, tmpFile.GetFullPath() );
if( !ret )
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.
* 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
/*
* Comparison routine for sorting by pin numbers.
*/
static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* item,
SCH_SHEET_PATH* path )
static bool sortPinsByNum( NETLIST_OBJECT* Pin1, NETLIST_OBJECT* Pin2 )
{
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 NETLIST_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* NETLIST_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;
// 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
// with "#" are not included in netlist (pseudo or virtual components)
wxString ref = comp->GetRef( path );
if( ref[0] == wxChar( '#' ) ) // ignore it
ref = comp->GetRef( aSheetPath );
if( ref[0] == wxChar( '#' ) )
continue;
// if( Component->m_FlagControlMulti == 1 )
@ -247,22 +333,28 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* item,
if( !entry )
continue;
// If Multi parts per package
// If component is a "multi parts per package" type
if( entry->GetPartCount() > 1 )
{
// test if already visited, and if so skip
if( s_ReferencesAlreadyFound.Lookup( ref ) )
if( m_ReferencesAlreadyFound.Lookup( ref ) )
continue;
// Collect all parts and pins for this first occurance of reference
FindAllInstancesOfComponent( comp, entry, path );
// Collect all parts and pins for this first occurance of reference.
// This is only done once, it would be too expensive otherwise.
FindAllInstancesOfComponent( comp, entry, aSheetPath );
if( ref == wxString( wxT("U1") ) )
{
printf("U1 m_SortedComponentPinList.size():%zu\n", m_SortedComponentPinList.size() );
}
}
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++ )
{
@ -270,16 +362,16 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* item,
wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE );
AddPinToComponentPinList( comp, path, pin );
AddPinToComponentPinList( comp, aSheetPath, pin );
}
}
// Sort pins in s_SortedComponentPinList by pin number
sort( s_SortedComponentPinList.begin(),
s_SortedComponentPinList.end(), SortPinsByNum );
// Sort pins in m_SortedComponentPinList by pin number
sort( m_SortedComponentPinList.begin(),
m_SortedComponentPinList.end(), sortPinsByNum );
// Remove duplicate Pins in s_SortedComponentPinList
EraseDuplicatePins( s_SortedComponentPinList );
// Remove duplicate Pins in m_SortedComponentPinList
EraseDuplicatePins( m_SortedComponentPinList );
return comp;
}
@ -288,48 +380,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
* is a convenience function that creates a new wxXmlNode with an optional textual child.
@ -353,7 +403,7 @@ static wxXmlNode* Node( const wxString& aName, const wxString& aTextualContent =
* creates a generic netlist, now in XML.
* @return bool - true if there were no errors, else false.
*/
bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName )
bool NETLIST_HELP::Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName )
{
#if 1
// output the XML format netlist.
@ -391,7 +441,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi
const wxString sPart = wxT( "part" );
const wxString sNames = wxT( "names" );
s_ReferencesAlreadyFound.Clear();
m_ReferencesAlreadyFound.Clear();
xdoc.SetRoot( xroot = Node( wxT( "netlist" ) ) );
xroot->AddProperty( wxT( "version" ), wxT( "B" ) );
@ -406,7 +456,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi
{
for( EDA_BaseStruct* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() )
{
SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( schItem, path );
SCH_COMPONENT* comp = findNextComponentAndCreatPinList( schItem, path );
if( !comp )
break; // No component left
@ -497,7 +547,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi
return false;
}
s_ReferencesAlreadyFound.Clear();
m_ReferencesAlreadyFound.Clear();
ret |= fprintf( out, "$BeginNetlist\n" );
@ -510,7 +560,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi
{
for( EDA_BaseStruct* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() )
{
SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( schItem, path );
SCH_COMPONENT* comp = findNextComponentAndCreatPinList( schItem, path );
if( !comp )
break; // No component left
@ -541,9 +591,9 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi
// Write pin list:
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 )
continue;
@ -586,7 +636,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi
* [.-] Or PSpice gnucap are beginning
* + + Gnucap and PSpice are ultimately NetList
*/
static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_netnames )
void NETLIST_HELP::WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_netnames )
{
char Line[1024];
SCH_SHEET_PATH* sheet;
@ -596,6 +646,7 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_
wxString text;
wxArrayString SpiceCommandAtBeginFile, SpiceCommandAtEndFile;
wxString msg;
wxString netName;
#define BUFYPOS_LEN 4
wxChar bufnum[BUFYPOS_LEN + 1];
@ -623,12 +674,15 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_
wxChar ident;
if( DrawList->Type() != TYPE_SCH_TEXT )
continue;
#define DRAWTEXT ( (SCH_TEXT*) DrawList )
text = DRAWTEXT->m_Text; if( text.IsEmpty() )
continue;
ident = text.GetChar( 0 );
if( ident != '.' && ident != '-' && ident != '+' )
continue;
text.Remove( 0, 1 ); // Remove the first char.
text.Remove( 6 ); // text contains 6 char.
text.MakeLower();
@ -673,34 +727,37 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_
// Create component list
s_ReferencesAlreadyFound.Clear();
m_ReferencesAlreadyFound.Clear();
for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
{
for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() )
{
DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet );
DrawList = Component = findNextComponentAndCreatPinList( DrawList, sheet );
if( Component == NULL )
break;
fprintf( f, "%s ", CONV_TO_UTF8( Component->GetRef( sheet ) ) );
// 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 )
continue;
wxString NetName = ReturnPinNetName( Pin, wxT( "N-%.6d" ) );
if( NetName.IsEmpty() )
NetName = wxT( "?" );
sprintPinNetName( &netName , wxT( "N-%.6d" ), Pin );
if( netName.IsEmpty() )
netName = wxT( "?" );
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
// "GND"
{
// NetName = "0" is "GND" net for Spice
if( NetName == wxT( "0" ) || NetName == wxT( "GND" ) )
if( netName == wxT( "0" ) || netName == wxT( "GND" ) )
fprintf( f, " 0" );
else
fprintf( f, " %d", Pin->GetNet() );
@ -712,7 +769,7 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_
}
}
s_SortedComponentPinList.clear();
m_SortedComponentPinList.clear();
/* Print texts starting by [+]pspice , ou [+]gnucap */
nbitems = SpiceCommandAtEndFile.GetCount();
@ -733,18 +790,13 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_
}
/* Generate 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
*/
static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with_pcbnew )
bool NETLIST_HELP::WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with_pcbnew )
{
wxString field;
wxString footprint;
char dateBuf[256];
int ret = 0; // zero now, OR in the sign bit on error
wxString netName;
std::vector<OBJ_CMP_TO_LIST> cmpList;
@ -757,7 +809,7 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
// Create netlist module section
s_ReferencesAlreadyFound.Clear();
m_ReferencesAlreadyFound.Clear();
SCH_SHEET_LIST sheetList;
@ -765,7 +817,7 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
{
for( EDA_BaseStruct* item = path->LastDrawList(); item; item = item->Next() )
{
SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( item, path );
SCH_COMPONENT* comp = findNextComponentAndCreatPinList( item, path );
if( !comp )
break;
@ -815,21 +867,24 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
}
ret |= fprintf( f, "\n" );
printf( "%-10s pincount:%zu\n", CONV_TO_UTF8( comp->GetRef( path ) ),
m_SortedComponentPinList.size() );
// 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 )
continue;
wxString netname = ReturnPinNetName( pin, wxT( "N-%.6d" ) );
if( netname.IsEmpty() )
netname = wxT( "?" );
sprintPinNetName( &netName, wxT( "N-%.6d" ), pin );
if( netName.IsEmpty() )
netName = wxT( "?" );
netname.Replace( wxT( " " ), wxT( "_" ) );
netName.Replace( wxT( " " ), wxT( "_" ) );
ret |= fprintf( f, " ( %4.4s %s )\n", (char*) &pin->m_PinNum,
CONV_TO_UTF8( netname ) );
CONV_TO_UTF8( netName ) );
}
ret |= fprintf( f, " )\n" );
@ -838,7 +893,7 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with
ret |= fprintf( f, ")\n*\n" );
s_SortedComponentPinList.clear();
m_SortedComponentPinList.clear();
// Write the allowed footprint list for each component
if( with_pcbnew && cmpList.size() )
@ -887,34 +942,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
* created by BuildNetList() in the table g_NetObjectslist
*/
static void AddPinToComponentPinList( SCH_COMPONENT* Component,
SCH_SHEET_PATH* sheetlist, LIB_PIN* Pin )
bool NETLIST_HELP::AddPinToComponentPinList( SCH_COMPONENT* aComponent,
SCH_SHEET_PATH* aSheetPath, LIB_PIN* aPin )
{
// Search the PIN description for Pin in g_NetObjectslist
for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ )
{
if( g_NetObjectslist[ii]->m_Type != NET_PIN )
continue;
if( g_NetObjectslist[ii]->m_Link != Component )
continue;
if( g_NetObjectslist[ii]->m_SheetList != *sheetlist )
continue;
if( g_NetObjectslist[ii]->m_PinNum != Pin->m_PinNum )
NETLIST_OBJECT* pin = g_NetObjectslist[ii];
if( pin->m_Type != NET_PIN )
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
DisplayError( NULL, wxT( "AddPinToComponentPinList err: MAXPIN reached" ) );
return;
}
return true; // we're done, we appended.
}
return false;
}
@ -932,7 +996,7 @@ static void AddPinToComponentPinList( SCH_COMPONENT* Component,
* given component.
* Note: this list *MUST* be sorted by pin number (.m_PinNum member value)
*/
static void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList )
void NETLIST_HELP::EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList )
{
if( aPinList.size() == 0 ) // Trivial case: component with no pin
return;
@ -959,6 +1023,7 @@ static void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList )
// other pin num end of duplicate list.
if( aPinList[idxref]->m_PinNum != aPinList[jj]->m_PinNum )
break;
if( aPinList[idxref]->m_FlagOfConnection == PAD_CONNECT )
aPinList[jj] = NULL;
else /* the reference pin is not connected: remove this pin if the
@ -980,81 +1045,83 @@ static void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList )
/**
* Function FindAllInstancesOfComponent
* is used for multiple parts per package components.
* is used for "multiple parts per package" components.
*
* Search all instances of Component_in,
* Calls AddPinToComponentPinList() to and pins founds to the current
* component pin list
*/
static void FindAllInstancesOfComponent( SCH_COMPONENT* Component_in,
void NETLIST_HELP::FindAllInstancesOfComponent( SCH_COMPONENT* aComponent,
LIB_COMPONENT* aEntry,
SCH_SHEET_PATH* Sheet_in )
SCH_SHEET_PATH* aSheetPath )
{
EDA_BaseStruct* SchItem;
SCH_COMPONENT* Component2;
LIB_PIN* pin;
SCH_SHEET_PATH* sheet;
wxString str, Reference = Component_in->GetRef( Sheet_in );
wxString ref = aComponent->GetRef( aSheetPath );
wxString ref2;
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;
Component2 = (SCH_COMPONENT*) SchItem;
SCH_COMPONENT* comp2 = (SCH_COMPONENT*) schItem;
str = Component2->GetRef( sheet );
if( str.CmpNoCase( Reference ) != 0 )
ref2 = comp2->GetRef( sheet );
if( ref2.CmpNoCase( ref ) != 0 )
continue;
if( aEntry == NULL )
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 );
if( pin->m_Unit
&& ( pin->m_Unit != Component2->GetUnitSelection( sheet ) ) )
if( pin->m_Unit && pin->m_Unit != comp2->GetUnitSelection( aSheetPath ) )
continue;
if( pin->m_Convert
&& ( pin->m_Convert != Component2->m_Convert ) )
if( pin->m_Convert && pin->m_Convert != comp2->m_Convert )
continue;
// A suitable pin in found: add it to the current list
AddPinToComponentPinList( Component2, sheet, pin );
#if defined(DEBUG)
printf( "AddPin %s %s\n", CONV_TO_UTF8(ref), CONV_TO_UTF8( pin->GetNumber() ) );
if( ref == wxString( wxT("U1") ) && pin->GetNumber() == wxString( wxT("A1") ) )
{
int debug = 1;
}
bool rc =
#endif
// A suitable pin is found: add it to the current list
AddPinToComponentPinList( comp2, aSheetPath, pin );
#if defined(DEBUG)
if( !rc )
{
printf("skipped pin %s %s\n",
CONV_TO_UTF8(ref),
CONV_TO_UTF8( pin->GetNumber() ) );
printf( "g_NetObjectslist.size():%zu\n",
g_NetObjectslist.size() );
}
#endif
}
}
}
}
/*
* 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
* connected
*/
static bool WriteGENERICListOfNetsTxt( FILE* f, NETLIST_OBJECT_LIST& aObjectsList )
bool NETLIST_HELP::WriteGENERICListOfNetsTxt( FILE* f, NETLIST_OBJECT_LIST& aObjectsList )
{
int ret = 0;
int netCode;
@ -1144,7 +1211,7 @@ static bool WriteGENERICListOfNetsTxt( FILE* f, NETLIST_OBJECT_LIST& aObjectsLis
* Function WriteGENERICListOfNets
* saves a netlist in xml format.
*/
static bool WriteGENERICListOfNets( wxXmlNode* aNode, NETLIST_OBJECT_LIST& aObjectsList )
bool NETLIST_HELP::WriteGENERICListOfNets( wxXmlNode* aNode, NETLIST_OBJECT_LIST& aObjectsList )
{
wxString netCodeTxt;
wxString netName;
@ -1255,7 +1322,7 @@ wxString StartLine( wxT( "." ) );
* .. B * T3 1
*U1 * 14
*/
static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
void NETLIST_HELP::WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
{
wxString StartCmpDesc = StartLine + wxT( "ADD_COM" );
wxString msg;
@ -1274,7 +1341,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
fprintf( f, "\n" );
// Create netlist module section
s_ReferencesAlreadyFound.Clear();
m_ReferencesAlreadyFound.Clear();
SCH_SHEET_LIST SheetList;
@ -1282,7 +1349,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
{
for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() )
{
DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet );
DrawList = Component = findNextComponentAndCreatPinList( DrawList, sheet );
if( Component == NULL )
break;
@ -1310,7 +1377,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
fprintf( f, "\n" );
s_SortedComponentPinList.clear();
m_SortedComponentPinList.clear();
WriteListOfNetsCADSTAR( f, g_NetObjectslist );
@ -1326,7 +1393,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
*. B U1 100
* 6 CA
*/
static void WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList )
void NETLIST_HELP::WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList )
{
wxString InitNetDesc = StartLine + wxT( "ADD_TER" );
wxString StartNetDesc = StartLine + wxT( "TER" );

View File

@ -18,7 +18,7 @@
// Buffer to build the list of items used in netlist and erc calculations
NETLIST_OBJECT_LIST g_NetObjectslist;
//#define NETLIST_DEBUG
#define NETLIST_DEBUG
static void PropageNetCode( int OldNetCode, int NewNetCode, int IsBus );
static void SheetLabelConnect( NETLIST_OBJECT* SheetLabel );

View File

@ -382,4 +382,4 @@ void MyFree( void* pt_mem );
void* MyZMalloc( 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 );
/**
* 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
* returns a pointer to the actual character data, either 8 or
* 16 bits wide, depending on how the wxWidgets library was compiled.
* returns a wxChar* to the actual character data within a wxString, and is
* 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 )
/* 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();
#else
return s.GetData();