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