You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

204 lines
6.5 KiB

  1. /**
  2. * @file netlist_reader.cpp
  3. */
  4. /*
  5. * This program source code file is part of KiCad, a free EDA CAD application.
  6. *
  7. * Copyright (C) 1992-2011 Jean-Pierre Charras.
  8. * Copyright (C) 2013-2016 Wayne Stambaugh <stambaughw@verizon.net>.
  9. * Copyright (C) 1992-2016 KiCad Developers, see change_log.txt for contributors.
  10. *
  11. * This program is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU General Public License
  13. * as published by the Free Software Foundation; either version 2
  14. * of the License, or (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, you may find one here:
  23. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  24. * or you may search the http://www.gnu.org website for the version 2 license,
  25. * or you may write to the Free Software Foundation, Inc.,
  26. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  27. */
  28. #include <kicad_string.h>
  29. #include <reporter.h>
  30. #include <pcb_netlist.h>
  31. #include <netlist_reader.h>
  32. #include <class_module.h>
  33. #include <wx/regex.h>
  34. NETLIST_READER::~NETLIST_READER()
  35. {
  36. delete m_lineReader;
  37. delete m_footprintReader;
  38. }
  39. NETLIST_READER::NETLIST_FILE_T NETLIST_READER::GuessNetlistFileType( LINE_READER* aLineReader )
  40. {
  41. // Orcad Pcb2 netlist format starts by "( {", followed by an unknown comment,
  42. // depending on the tool which created the file
  43. wxRegEx reOrcad( wxT( "(?i)[ ]*\\([ \t]+{+" ), wxRE_ADVANCED );
  44. wxASSERT( reOrcad.IsValid() );
  45. // Our legacy netlist format starts by "# EESchema Netlist "
  46. wxRegEx reLegacy( wxT( "(?i)#[ \t]+EESchema[ \t]+Netlist[ \t]+" ), wxRE_ADVANCED );
  47. wxASSERT( reLegacy.IsValid() );
  48. // Our new netlist format starts by "(export (version "
  49. wxRegEx reKicad( wxT( "[ ]*\\(export[ ]+" ), wxRE_ADVANCED );
  50. wxASSERT( reKicad.IsValid() );
  51. wxString line;
  52. while( aLineReader->ReadLine() )
  53. {
  54. line = FROM_UTF8( aLineReader->Line() );
  55. if( reLegacy.Matches( line ) )
  56. return LEGACY;
  57. else if( reKicad.Matches( line ) )
  58. return KICAD;
  59. else if( reOrcad.Matches( line ) )
  60. return ORCAD;
  61. }
  62. return UNKNOWN;
  63. }
  64. NETLIST_READER* NETLIST_READER::GetNetlistReader( NETLIST* aNetlist,
  65. const wxString& aNetlistFileName,
  66. const wxString& aCompFootprintFileName )
  67. {
  68. wxASSERT( aNetlist != NULL );
  69. std::unique_ptr< FILE_LINE_READER > file_rdr(new FILE_LINE_READER( aNetlistFileName ) );
  70. NETLIST_FILE_T type = GuessNetlistFileType( file_rdr.get() );
  71. file_rdr->Rewind();
  72. // The component footprint link reader is NULL if no file name was specified.
  73. std::unique_ptr<CMP_READER> cmp_rdr( aCompFootprintFileName.IsEmpty() ?
  74. NULL :
  75. new CMP_READER( new FILE_LINE_READER( aCompFootprintFileName ) ) );
  76. switch( type )
  77. {
  78. case LEGACY:
  79. case ORCAD:
  80. return new LEGACY_NETLIST_READER( file_rdr.release(), aNetlist, cmp_rdr.release() );
  81. case KICAD:
  82. return new KICAD_NETLIST_READER( file_rdr.release(), aNetlist, cmp_rdr.release() );
  83. default: // Unrecognized format:
  84. break;
  85. }
  86. return NULL;
  87. }
  88. bool CMP_READER::Load( NETLIST* aNetlist )
  89. {
  90. wxCHECK_MSG( aNetlist != NULL,true, wxT( "No netlist passed to CMP_READER::Load()" ) );
  91. wxString reference; // Stores value read from line like Reference = BUS1;
  92. wxString timestamp; // Stores value read from line like TimeStamp = /32307DE2/AA450F67;
  93. wxString footprint; // Stores value read from line like IdModule = CP6;
  94. wxString buffer;
  95. wxString value;
  96. bool ok = true;
  97. while( m_lineReader->ReadLine() )
  98. {
  99. buffer = FROM_UTF8( m_lineReader->Line() );
  100. if( !buffer.StartsWith( wxT( "BeginCmp" ) ) )
  101. continue;
  102. // Begin component description.
  103. reference.Empty();
  104. footprint.Empty();
  105. timestamp.Empty();
  106. while( m_lineReader->ReadLine() )
  107. {
  108. buffer = FROM_UTF8( m_lineReader->Line() );
  109. if( buffer.StartsWith( wxT( "EndCmp" ) ) )
  110. break;
  111. // store string value, stored between '=' and ';' delimiters.
  112. value = buffer.AfterFirst( '=' );
  113. value = value.BeforeLast( ';' );
  114. value.Trim( true );
  115. value.Trim( false );
  116. if( buffer.StartsWith( wxT( "Reference" ) ) )
  117. {
  118. reference = value;
  119. continue;
  120. }
  121. if( buffer.StartsWith( wxT( "IdModule =" ) ) )
  122. {
  123. footprint = value;
  124. continue;
  125. }
  126. if( buffer.StartsWith( wxT( "TimeStamp =" ) ) )
  127. {
  128. timestamp = value;
  129. continue;
  130. }
  131. }
  132. // Find the corresponding item in component list:
  133. COMPONENT* component = aNetlist->GetComponentByReference( reference );
  134. // The corresponding component could no longer existing in the netlist. This
  135. // can happen when it is removed from schematic and still exists in footprint
  136. // assignment list. This is an usual case during the life of a design.
  137. if( component )
  138. {
  139. LIB_ID fpid;
  140. if( !footprint.IsEmpty() && fpid.Parse( footprint ) >= 0 )
  141. {
  142. wxString error;
  143. error.Printf( _( "invalid footprint ID in\nfile: \"%s\"\nline: %d" ),
  144. GetChars( m_lineReader->GetSource() ),
  145. m_lineReader->LineNumber() );
  146. THROW_IO_ERROR( error );
  147. }
  148. // For checking purpose, store the existing LIB_ID (if any) in the alternate fpid copy
  149. // if this existing LIB_ID differs from the LIB_ID read from the .cmp file.
  150. // CvPcb can ask for user to chose the right LIB_ID.
  151. // It happens if the LIB_ID was modified outside CvPcb.
  152. if( fpid != component->GetFPID() && !component->GetFPID().empty() )
  153. component->SetAltFPID( component->GetFPID() );
  154. component->SetFPID( fpid );
  155. }
  156. else
  157. {
  158. ok = false; // can be used to display a warning in Pcbnew.
  159. }
  160. }
  161. return ok;
  162. }