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 <stambaughw@verizon.net>.
9  * Copyright (C) 1992-2017 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 <kicad_string.h>
32 #include <reporter.h>
33 
34 #include <pcb_netlist.h>
35 #include <netlist_reader.h>
36 #include <class_module.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  // Our legacy netlist format starts by "# EESchema Netlist "
55  wxRegEx reLegacy( wxT( "(?i)#[ \t]+EESchema[ \t]+Netlist[ \t]+" ), wxRE_ADVANCED );
56  wxASSERT( reLegacy.IsValid() );
57  // Our new netlist format starts by "(export (version "
58  wxRegEx reKicad( wxT( "[ ]*\\(export[ ]+" ), wxRE_ADVANCED );
59  wxASSERT( reKicad.IsValid() );
60 
61  wxString line;
62 
63  while( aLineReader->ReadLine() )
64  {
65  line = FROM_UTF8( aLineReader->Line() );
66 
67  if( reLegacy.Matches( line ) )
68  return LEGACY;
69  else if( reKicad.Matches( line ) )
70  return KICAD;
71  else if( reOrcad.Matches( line ) )
72  return ORCAD;
73  }
74 
75  return UNKNOWN;
76 }
77 
78 
80  const wxString& aNetlistFileName,
81  const wxString& aCompFootprintFileName )
82  throw( IO_ERROR )
83 {
84  wxASSERT( aNetlist != NULL );
85 
86  std::unique_ptr< FILE_LINE_READER > file_rdr(new FILE_LINE_READER( aNetlistFileName ) );
87 
88  NETLIST_FILE_T type = GuessNetlistFileType( file_rdr.get() );
89  file_rdr->Rewind();
90 
91  // The component footprint link reader is NULL if no file name was specified.
92  std::unique_ptr<CMP_READER> cmp_rdr( aCompFootprintFileName.IsEmpty() ?
93  NULL :
94  new CMP_READER( new FILE_LINE_READER( aCompFootprintFileName ) ) );
95 
96  switch( type )
97  {
98  case LEGACY:
99  case ORCAD:
100  return new LEGACY_NETLIST_READER( file_rdr.release(), aNetlist, cmp_rdr.release() );
101 
102  case KICAD:
103  return new KICAD_NETLIST_READER( file_rdr.release(), aNetlist, cmp_rdr.release() );
104 
105  default: // Unrecognized format:
106  break;
107  }
108 
109  return NULL;
110 }
111 
112 
113 bool CMP_READER::Load( NETLIST* aNetlist ) throw( IO_ERROR, PARSE_ERROR )
114 {
115  wxCHECK_MSG( aNetlist != NULL,true, wxT( "No netlist passed to CMP_READER::Load()" ) );
116 
117  wxString reference; // Stores value read from line like Reference = BUS1;
118  wxString timestamp; // Stores value read from line like TimeStamp = /32307DE2/AA450F67;
119  wxString footprint; // Stores value read from line like IdModule = CP6;
120  wxString buffer;
121  wxString value;
122 
123  bool ok = true;
124 
125  while( m_lineReader->ReadLine() )
126  {
127  buffer = FROM_UTF8( m_lineReader->Line() );
128 
129  if( !buffer.StartsWith( wxT( "BeginCmp" ) ) )
130  continue;
131 
132  // Begin component description.
133  reference.Empty();
134  footprint.Empty();
135  timestamp.Empty();
136 
137  while( m_lineReader->ReadLine() )
138  {
139  buffer = FROM_UTF8( m_lineReader->Line() );
140 
141  if( buffer.StartsWith( wxT( "EndCmp" ) ) )
142  break;
143 
144  // store string value, stored between '=' and ';' delimiters.
145  value = buffer.AfterFirst( '=' );
146  value = value.BeforeLast( ';' );
147  value.Trim( true );
148  value.Trim( false );
149 
150  if( buffer.StartsWith( wxT( "Reference" ) ) )
151  {
152  reference = value;
153  continue;
154  }
155 
156  if( buffer.StartsWith( wxT( "IdModule =" ) ) )
157  {
158  footprint = value;
159  continue;
160  }
161 
162  if( buffer.StartsWith( wxT( "TimeStamp =" ) ) )
163  {
164  timestamp = value;
165  continue;
166  }
167  }
168 
169  // Find the corresponding item in component list:
170  COMPONENT* component = aNetlist->GetComponentByReference( reference );
171 
172  // The corresponding component could no longer existing in the netlist. This
173  // can happen when it is removed from schematic and still exists in footprint
174  // assignment list. This is an usual case during the life of a design.
175  if( component )
176  {
177  LIB_ID fpid;
178 
179  if( !footprint.IsEmpty() && fpid.Parse( TO_UTF8( footprint ) ) >= 0 )
180  {
181  wxString error;
182  error.Printf( _( "invalid footprint ID in\nfile: <%s>\nline: %d" ),
183  GetChars( m_lineReader->GetSource() ),
184  m_lineReader->LineNumber() );
185 
186  THROW_IO_ERROR( error );
187  }
188 
189  // For checking purpose, store the existing LIB_ID (if any) in the alternate fpid copy
190  // if this existing LIB_ID differs from the LIB_ID read from the .cmp file.
191  // CvPcb can ask for user to chose the right LIB_ID.
192  // It happens if the LIB_ID was modified outside CvPcb.
193  if( fpid != component->GetFPID() && !component->GetFPID().empty() )
194  component->SetAltFPID( component->GetFPID() );
195 
196  component->SetFPID( fpid );
197  }
198  else
199  {
200  ok = false; // can be used to display a warning in Pcbnew.
201  }
202  }
203 
204  return ok;
205 }
void SetAltFPID(const LIB_ID &aFPID)
Definition: pcb_netlist.h:159
Class LINE_READER is an abstract class from which implementation specific LINE_READERs may be derived...
Definition: richio.h:81
static NETLIST_FILE_T GuessNetlistFileType(LINE_READER *aLineReader)
Function GuessNetlistFileType looks at aFileHeaderLine to see if it matches any of the netlist file t...
bool empty() const
Function empty.
Definition: lib_id.h:199
const LIB_ID & GetFPID() const
Definition: pcb_netlist.h:164
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
Class KICAD_NETLIST_READER read the new s-expression based KiCad netlist format.
void SetFPID(const LIB_ID &aFPID)
Definition: pcb_netlist.h:153
static NETLIST_READER * GetNetlistReader(NETLIST *aNetlist, const wxString &aNetlistFileName, const wxString &aCompFootprintFileName=wxEmptyString)
Function GetNetlistReader attempts to determine the net list file type of aNetlistFileName and return...
int Parse(const UTF8 &aId)
Function Parse.
Definition: lib_id.cpp:122
Class LIB_ID.
Definition: lib_id.h:56
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
bool Load(NETLIST *aNetlist)
Function Load read the *.cmp file format contains the component footprint assignments created by CvPc...
Class FILE_LINE_READER is a LINE_READER that reads from an open file.
Definition: richio.h:180
Class NETLIST stores all of information read from a netlist along with the flags used to update the N...
Definition: pcb_netlist.h:205
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:139
virtual ~NETLIST_READER()
Class NETLIST_READER is a pure virtual class to derive a specific type of netlist reader from...
#define THROW_IO_ERROR(x)
Definition: utf8.cpp:60
Class LEGACY_NETLIST_READER reads the KiCad legacy and the old Orcad netlist formats.
Class COMPONENT is used to store components and all of their related information found in a netlist...
Definition: pcb_netlist.h:83
Struct PARSE_ERROR contains a filename or source description, a problem input line, a line number, a byte offset, and an error message which contains the the caller's report and his call site information: CPP source file, function, and line number.
Definition: ki_exception.h:94
Class CMP_READER reads a component footprint link file (*.cmp) format.
virtual char * ReadLine()=0
Function ReadLine reads a line of text into the buffer and increments the line number counter...
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
LINE_READER * m_lineReader
The line reader of the netlist.
Module description (excepted pads)
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:47
CMP_READER * m_footprintReader
The reader used to load the footprint links. If NULL, footprint links are not read.