KiCad PCB EDA Suite
netlist_reader.cpp
Go to the documentation of this file.
1 
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 <[email protected]>.
9  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.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 
29 
30 
31 #include <string_utils.h>
32 #include <reporter.h>
33 
34 #include "pcb_netlist.h"
35 #include "netlist_reader.h"
36 #include <footprint.h>
37 
38 #include <wx/regex.h>
39 
40 
42 {
43  delete m_lineReader;
44  delete m_footprintReader;
45 }
46 
47 
49 {
50  // Orcad Pcb2 netlist format starts by "( {", followed by an unknown comment,
51  // depending on the tool which created the file
52  wxRegEx reOrcad( wxT( "(?i)[ ]*\\([ \t]+{+" ), wxRE_ADVANCED );
53  wxASSERT( reOrcad.IsValid() );
54 
55  // Our legacy netlist format starts by "# EESchema Netlist "
56  wxRegEx reLegacy( wxT( "(?i)#[ \t]+EESchema[ \t]+Netlist[ \t]+" ), wxRE_ADVANCED );
57  wxASSERT( reLegacy.IsValid() );
58 
59  // Our new netlist format starts by "(export (version "
60  wxRegEx reKicad( wxT( "[ ]*\\(export[ ]+" ), wxRE_ADVANCED );
61  wxASSERT( reKicad.IsValid() );
62 
63  wxString line;
64 
65  while( aLineReader->ReadLine() )
66  {
67  line = FROM_UTF8( aLineReader->Line() );
68 
69  if( reLegacy.Matches( line ) )
70  return LEGACY;
71  else if( reKicad.Matches( line ) )
72  return KICAD;
73  else if( reOrcad.Matches( line ) )
74  return ORCAD;
75  }
76 
77  return UNKNOWN;
78 }
79 
80 
82  const wxString& aNetlistFileName,
83  const wxString& aCompFootprintFileName )
84 {
85  wxASSERT( aNetlist != nullptr );
86 
87  std::unique_ptr<FILE_LINE_READER> file_rdr =
88  std::make_unique<FILE_LINE_READER>( aNetlistFileName );
89 
90  NETLIST_FILE_T type = GuessNetlistFileType( file_rdr.get() );
91  file_rdr->Rewind();
92 
93  // The component footprint link reader is NULL if no file name was specified.
94  std::unique_ptr<CMP_READER> cmp_rdr( aCompFootprintFileName.IsEmpty() ?
95  nullptr :
96  new CMP_READER( new FILE_LINE_READER( aCompFootprintFileName ) ) );
97 
98  switch( type )
99  {
100  case LEGACY:
101  case ORCAD:
102  return new LEGACY_NETLIST_READER( file_rdr.release(), aNetlist, cmp_rdr.release() );
103 
104  case KICAD:
105  return new KICAD_NETLIST_READER( file_rdr.release(), aNetlist, cmp_rdr.release() );
106 
107  default: // Unrecognized format:
108  break;
109  }
110 
111  return nullptr;
112 }
113 
114 
115 bool CMP_READER::Load( NETLIST* aNetlist )
116 {
117  wxCHECK_MSG( aNetlist != nullptr, true, wxT( "No netlist passed to CMP_READER::Load()" ) );
118 
119  wxString reference; // Stores value read from line like Reference = BUS1;
120  wxString timestamp; // Stores value read from line like TimeStamp = /32307DE2/AA450F67;
121  wxString footprint; // Stores value read from line like IdModule = CP6;
122  wxString buffer;
123  wxString value;
124 
125  bool ok = true;
126 
127  while( m_lineReader->ReadLine() )
128  {
129  buffer = FROM_UTF8( m_lineReader->Line() );
130 
131  if( !buffer.StartsWith( wxT( "BeginCmp" ) ) )
132  continue;
133 
134  // Begin component description.
135  reference.Empty();
136  footprint.Empty();
137  timestamp.Empty();
138 
139  while( m_lineReader->ReadLine() )
140  {
141  buffer = FROM_UTF8( m_lineReader->Line() );
142 
143  if( buffer.StartsWith( wxT( "EndCmp" ) ) )
144  break;
145 
146  // store string value, stored between '=' and ';' delimiters.
147  value = buffer.AfterFirst( '=' );
148  value = value.BeforeLast( ';' );
149  value.Trim( true );
150  value.Trim( false );
151 
152  if( buffer.StartsWith( wxT( "Reference" ) ) )
153  {
154  reference = value;
155  continue;
156  }
157 
158  if( buffer.StartsWith( wxT( "IdModule =" ) ) )
159  {
160  footprint = value;
161  continue;
162  }
163 
164  if( buffer.StartsWith( wxT( "TimeStamp =" ) ) )
165  {
166  timestamp = value;
167  continue;
168  }
169  }
170 
171  // Find the corresponding item in component list:
172  COMPONENT* component = aNetlist->GetComponentByReference( reference );
173 
174  // The corresponding component could no longer existing in the netlist. This
175  // can happen when it is removed from schematic and still exists in footprint
176  // assignment list. This is an usual case during the life of a design.
177  if( component )
178  {
179  LIB_ID fpid;
180 
181  if( !footprint.IsEmpty() && fpid.Parse( footprint, true ) >= 0 )
182  {
183  wxString error;
184  error.Printf( _( "Invalid footprint ID in\nfile: '%s'\nline: %d" ),
186 
187  THROW_IO_ERROR( error );
188  }
189 
190  // For checking purpose, store the existing LIB_ID (if any) in the alternate fpid copy
191  // if this existing LIB_ID differs from the LIB_ID read from the .cmp file.
192  // CvPcb can ask for user to chose the right LIB_ID.
193  // It happens if the LIB_ID was modified outside CvPcb.
194  if( fpid != component->GetFPID() && !component->GetFPID().empty() )
195  component->SetAltFPID( component->GetFPID() );
196 
197  component->SetFPID( fpid );
198  }
199  else
200  {
201  ok = false; // can be used to display a warning in Pcbnew.
202  }
203  }
204 
205  return ok;
206 }
void SetAltFPID(const LIB_ID &aFPID)
Definition: pcb_netlist.h:135
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
Definition: richio.h:80
static NETLIST_FILE_T GuessNetlistFileType(LINE_READER *aLineReader)
Look at aFileHeaderLine to see if it matches any of the netlist file types it knows about.
char * Line() const
Return a pointer to the last line that was read in.
Definition: richio.h:117
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:110
Read the new s-expression based KiCad netlist format.
virtual const wxString & GetSource() const
Returns the name of the source of the lines in an abstract sense.
Definition: richio.h:109
void SetFPID(const LIB_ID &aFPID)
Definition: pcb_netlist.h:132
LINE_READER * m_lineReader
The line reader to read.
static NETLIST_READER * GetNetlistReader(NETLIST *aNetlist, const wxString &aNetlistFileName, const wxString &aCompFootprintFileName=wxEmptyString)
Attempt to determine the net list file type of aNetlistFileName and return the appropriate NETLIST_RE...
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
bool empty() const
Definition: lib_id.h:180
const LIB_ID & GetFPID() const
Definition: pcb_netlist.h:133
bool Load(NETLIST *aNetlist)
Read the *.cmp file format contains the component footprint assignments created by CvPcb into aNetlis...
A LINE_READER that reads from an open file.
Definition: richio.h:172
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
Definition: pcb_netlist.h:206
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
Definition: richio.h:135
virtual ~NETLIST_READER()
A pure virtual class to derive a specific type of netlist reader from.
#define _(s)
Read the KiCad legacy and the old Orcad netlist formats.
Store all of the related footprint information found in a netlist.
Definition: pcb_netlist.h:84
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:49
Read a component footprint link file (*.cmp) format.
virtual char * ReadLine()=0
Read a line of text into the buffer and increments the line number counter.
COMPONENT * GetComponentByReference(const wxString &aReference)
Return a COMPONENT by aReference.
LINE_READER * m_lineReader
The line reader of the netlist.
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
CMP_READER * m_footprintReader
The reader used to load the footprint links. If NULL, footprint links are not read.