KiCad PCB EDA Suite
kicad_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) 1992-2016 KiCad Developers, see change_log.txt for contributors.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, you may find one here:
22  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23  * or you may search the http://www.gnu.org website for the version 2 license,
24  * or you may write to the Free Software Foundation, Inc.,
25  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26  */
27 
28 #include <wx/wx.h>
29 #include <netlist_lexer.h> // netlist_lexer is common to Eeschema and Pcbnew
30 #include <macros.h>
31 
32 #include <pcb_netlist.h>
33 #include <netlist_reader.h>
34 
35 using namespace NL_T;
36 
37 
39 {
40  m_parser->Parse();
41 
42  if( m_footprintReader )
43  {
44  m_footprintReader->Load( m_netlist );
45 
46  // Sort the component pins so they are in the same order as the legacy format. This
47  // is useful for comparing legacy and s-expression netlist dumps.
48  for( unsigned i = 0; i < m_netlist->GetCount(); i++ )
49  m_netlist->GetComponent( i )->SortPins();
50  }
51 }
52 
53 
54 // KICAD_NETLIST_PARSER
56  NETLIST_LEXER( aReader )
57 {
58  m_lineReader = aReader;
59  m_netlist = aNetlist;
60  token = T_NONE;
61 }
62 
63 
65 {
66  int curr_level = 0;
67 
68  while( ( token = NextTok() ) != T_EOF )
69  {
70  if( token == T_LEFT )
71  curr_level--;
72 
73  if( token == T_RIGHT )
74  {
75  curr_level++;
76 
77  if( curr_level > 0 )
78  return;
79  }
80  }
81 }
82 
83 
85 {
86  int plevel = 0; // the count of ')' to read and end of file,
87  // after parsing all sections
88 
89  while( ( token = NextTok() ) != T_EOF )
90  {
91  if( token == T_LEFT )
92  token = NextTok();
93 
94  switch( token )
95  {
96  case T_export: // The netlist starts here.
97  // nothing to do here,
98  // just increment the count of ')' to read and end of file
99  plevel++;
100  break;
101 
102  case T_version: // The netlist starts here.
103  // version id not yet used: read it but does not use it
104  NextTok();
105  NeedRIGHT();
106  break;
107 
108  case T_components: // The section comp starts here.
109  while( ( token = NextTok() ) != T_RIGHT )
110  {
111  if( token == T_LEFT )
112  token = NextTok();
113 
114  if( token == T_comp ) // A component section found. Read it
115  parseComponent();
116  }
117 
118  break;
119 
120  case T_nets: // The section nets starts here.
121  while( ( token = NextTok() ) != T_RIGHT )
122  {
123  if( token == T_LEFT )
124  token = NextTok();
125 
126  if( token == T_net )
127  {
128  // A net section if found. Read it
129  parseNet();
130  }
131  }
132 
133  break;
134 
135  case T_libparts: // The section libparts starts here.
136  while( ( token = NextTok() ) != T_RIGHT )
137  {
138  if( token == T_LEFT )
139  token = NextTok();
140 
141  if( token == T_libpart )
142  {
143  // A libpart section if found. Read it
145  }
146  }
147 
148  break;
149 
150  case T_libraries: // The section libraries starts here.
151  // List of libraries in use.
152  // Not used here, just skip it
153  skipCurrent();
154  break;
155 
156  case T_design: // The section design starts here.
157  // Not used (mainly they are comments), just skip it
158  skipCurrent();
159  break;
160 
161  case T_RIGHT: // The closing parenthesis of the file.
162  // Not used (mainly they are comments), just skip it
163  plevel--;
164  break;
165 
166  default:
167  skipCurrent();
168  break;
169  }
170  }
171 
172  if( plevel != 0 )
173  {
174  wxLogDebug( wxT( "KICAD_NETLIST_PARSER::Parse(): bad parenthesis count (count = %d"),
175  plevel );
176  }
177 }
178 
179 
181 {
182  /* Parses a section like
183  * (net (code 20) (name /PC-A0)
184  * (node (ref BUS1) (pin 62))
185  * (node (ref U3) (pin 3))
186  * (node (ref U9) (pin M6)))
187  */
188 
189  COMPONENT* component = NULL;
190  wxString code;
191  wxString name;
192  wxString reference;
193  wxString pin;
194  int nodecount = 0;
195 
196  // The token net was read, so the next data is (code <number>)
197  while( (token = NextTok()) != T_RIGHT )
198  {
199  if( token == T_LEFT )
200  token = NextTok();
201 
202  switch( token )
203  {
204  case T_code:
205  NeedSYMBOLorNUMBER();
206  code = FROM_UTF8( CurText() );
207  NeedRIGHT();
208  break;
209 
210  case T_name:
211  NeedSYMBOLorNUMBER();
212  name = FROM_UTF8( CurText() );
213  NeedRIGHT();
214 
215  if( name.IsEmpty() ) // Give a dummy net name like N-000109
216  name = wxT("N-00000") + code;
217 
218  break;
219 
220  case T_node:
221  while( (token = NextTok()) != T_RIGHT )
222  {
223  if( token == T_LEFT )
224  token = NextTok();
225 
226  switch( token )
227  {
228  case T_ref:
229  NeedSYMBOLorNUMBER();
230  reference = FROM_UTF8( CurText() );
231  NeedRIGHT();
232  break;
233 
234  case T_pin:
235  NeedSYMBOLorNUMBER();
236  pin = FROM_UTF8( CurText() );
237  NeedRIGHT();
238  break;
239 
240  default:
241  skipCurrent();
242  break;
243  }
244  }
245 
246 
247  component = m_netlist->GetComponentByReference( reference );
248 
249  // Cannot happen if the netlist is valid.
250  if( component == NULL )
251  {
252  wxString msg;
253  msg.Printf( _( "Cannot find component with reference \"%s\" in netlist." ),
254  GetChars( reference ) );
257  }
258 
259  component->AddNet( pin, name );
260  nodecount++;
261  break;
262 
263  default:
264  skipCurrent();
265  break;
266  }
267  }
268 }
269 
270 
272 {
273  /* Parses a section like
274  * (comp (ref P1)
275  * (value DB25FEMELLE)
276  * (footprint DB25FC)
277  * (libsource (lib conn) (part DB25))
278  * (sheetpath (names /) (tstamps /))
279  * (tstamp 3256759C))
280  *
281  * other fields (unused) are skipped
282  * A component need a reference, value, footprint name and a full time stamp
283  * The full time stamp is the sheetpath time stamp + the component time stamp
284  */
285  LIB_ID fpid;
286  wxString footprint;
287  wxString ref;
288  wxString value;
289  wxString library;
290  wxString name;
291  wxString pathtimestamp, timestamp;
292 
293  // The token comp was read, so the next data is (ref P1)
294  while( (token = NextTok()) != T_RIGHT )
295  {
296  if( token == T_LEFT )
297  token = NextTok();
298 
299  switch( token )
300  {
301  case T_ref:
302  NeedSYMBOLorNUMBER();
303  ref = FROM_UTF8( CurText() );
304  NeedRIGHT();
305  break;
306 
307  case T_value:
308  NeedSYMBOLorNUMBER();
309  value = FROM_UTF8( CurText() );
310  NeedRIGHT();
311  break;
312 
313  case T_footprint:
314  NeedSYMBOLorNUMBER();
315  footprint = FromUTF8();
316  NeedRIGHT();
317  break;
318 
319  case T_libsource:
320  // Read libsource
321  while( (token = NextTok()) != T_RIGHT )
322  {
323  if( token == T_LEFT )
324  token = NextTok();
325 
326  if( token == T_lib )
327  {
328  NeedSYMBOLorNUMBER();
329  library = FROM_UTF8( CurText() );
330  NeedRIGHT();
331  }
332  else if( token == T_part )
333  {
334  NeedSYMBOLorNUMBER();
335  name = FROM_UTF8( CurText() );
336  NeedRIGHT();
337  }
338  else if( token == T_description )
339  {
340  NeedSYMBOLorNUMBER();
341  NeedRIGHT();
342  }
343  else
344  {
345  Expecting( "part, lib or description" );
346  }
347  }
348  break;
349 
350  case T_sheetpath:
351  while( ( token = NextTok() ) != T_tstamps );
352  NeedSYMBOLorNUMBER();
353  pathtimestamp = FROM_UTF8( CurText() );
354  NeedRIGHT();
355  NeedRIGHT();
356  break;
357 
358  case T_tstamp:
359  NeedSYMBOLorNUMBER();
360  timestamp = FROM_UTF8( CurText() );
361  NeedRIGHT();
362  break;
363 
364  default:
365  // Skip not used data (i.e all other tokens)
366  skipCurrent();
367  break;
368  }
369  }
370 
371  if( !footprint.IsEmpty() && fpid.Parse( footprint, LIB_ID::ID_PCB, true ) >= 0 )
372  {
373  wxString error;
374  error.Printf( _( "invalid footprint ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
375  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
376 
377  THROW_IO_ERROR( error );
378  }
379 
380  pathtimestamp += timestamp;
381  COMPONENT* component = new COMPONENT( fpid, ref, value, pathtimestamp );
382  component->SetName( name );
383  component->SetLibrary( library );
384  m_netlist->AddComponent( component );
385 }
386 
387 
389 {
390  /* Parses a section like
391  * (libpart (lib device) (part C)
392  * (aliases
393  * (alias Cxx)
394  * (alias Cyy))
395  * (description "Condensateur non polarise")
396  * (footprints
397  * (fp SM*)
398  * (fp C?)
399  * (fp C1-1))
400  * (fields
401  * (field (name Reference) C)
402  * (field (name Value) C))
403  * (pins
404  * (pin (num 1) (name ~) (type passive))
405  * (pin (num 2) (name ~) (type passive))))
406  *
407  * Currently footprints section/fp are read and data stored
408  * other fields (unused) are skipped
409  */
410  COMPONENT* component = NULL;
411  wxString libName;
412  wxString libPartName;
413  wxArrayString footprintFilters;
414  wxArrayString aliases;
415  int pinCount = 0;
416 
417  // The last token read was libpart, so read the next token
418  while( (token = NextTok()) != T_RIGHT )
419  {
420  if( token == T_LEFT )
421  token = NextTok();
422 
423  switch( token )
424  {
425  case T_lib:
426  NeedSYMBOLorNUMBER();
427  libName = FROM_UTF8( CurText() );
428  NeedRIGHT();
429  break;
430 
431  case T_part:
432  NeedSYMBOLorNUMBER();
433  libPartName = FROM_UTF8( CurText() );
434  NeedRIGHT();
435  break;
436 
437  case T_footprints:
438  // Read all fp elements (footprint filter item)
439  while( (token = NextTok()) != T_RIGHT )
440  {
441  if( token == T_LEFT )
442  token = NextTok();
443 
444  if( token != T_fp )
445  Expecting( T_fp );
446 
447  NeedSYMBOLorNUMBER();
448  footprintFilters.Add( FROM_UTF8( CurText() ) );
449  NeedRIGHT();
450  }
451  break;
452 
453  case T_aliases:
454  while( (token = NextTok()) != T_RIGHT )
455  {
456  if( token == T_LEFT )
457  token = NextTok();
458 
459  if( token != T_alias )
460  Expecting( T_alias );
461 
462  NeedSYMBOLorNUMBER();
463  aliases.Add( FROM_UTF8( CurText() ) );
464  NeedRIGHT();
465  }
466  break;
467 
468  case T_pins:
469  while( (token = NextTok()) != T_RIGHT )
470  {
471  if( token == T_LEFT )
472  token = NextTok();
473 
474  if( token != T_pin )
475  Expecting( T_pin );
476 
477  pinCount++;
478 
479  skipCurrent();
480  }
481  break;
482 
483  default:
484  // Skip not used data (i.e all other tokens)
485  skipCurrent();
486  break;
487  }
488  }
489 
490  // Find all of the components that reference this component library part definition.
491  for( unsigned i = 0; i < m_netlist->GetCount(); i++ )
492  {
493  component = m_netlist->GetComponent( i );
494 
495  if( component->IsLibSource( libName, libPartName ) )
496  {
497  component->SetFootprintFilters( footprintFilters );
498  component->SetPinCount( pinCount );
499  }
500 
501  for( unsigned jj = 0; jj < aliases.GetCount(); jj++ )
502  {
503  if( component->IsLibSource( libName, aliases[jj] ) )
504  {
505  component->SetFootprintFilters( footprintFilters );
506  component->SetPinCount( pinCount );
507  }
508  }
509 
510  }
511 }
bool IsLibSource(const wxString &aLibrary, const wxString &aName) const
Definition: pcb_netlist.h:193
Class LINE_READER is an abstract class from which implementation specific LINE_READERs may be derived...
Definition: richio.h:81
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:139
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:61
virtual const wxString & GetSource() const
Function GetSource returns the name of the source of the lines in an abstract sense.
Definition: richio.h:130
void SetLibrary(const wxString &aLibrary)
Definition: pcb_netlist.h:148
NETLIST * m_netlist
The netlist to parse into. Not owned.
void parseComponent()
Function parseComponent parse a component description: (comp (ref P1) (value DB25FEMELLE) (footprint ...
void skipCurrent()
Function skipCurrent Skip the current token level, i.e search for the RIGHT parenthesis which closes ...
unsigned GetCount() const
Function GetCount.
Definition: pcb_netlist.h:256
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
This file contains miscellaneous commonly used macros and functions.
void AddComponent(COMPONENT *aComponent)
Function AddComponent adds aComponent to the NETLIST.
virtual void LoadNetlist() override
Function LoadNetlist loads the contents of the netlist file into aNetlist.
KICAD_NETLIST_PARSER(LINE_READER *aReader, NETLIST *aNetlist)
void SetFootprintFilters(const wxArrayString &aFilterList)
Definition: pcb_netlist.h:172
void parseLibPartList()
Function parseLibPartList reads the section "libparts" in the netlist: (libparts (libpart (lib device...
Class NETLIST stores all of information read from a netlist along with the flags used to update the N...
Definition: pcb_netlist.h:214
LINE_READER * m_lineReader
The line reader used to parse the netlist. Not owned.
virtual unsigned LineNumber() const
Function Line Number returns the line number of the last line read from this LINE_READER.
Definition: richio.h:159
void SetPinCount(int aPinCount)
Definition: pcb_netlist.h:179
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Class COMPONENT is used to store components and all of their related information found in a netlist.
Definition: pcb_netlist.h:83
unsigned Length() const
Function Length returns the number of bytes in the last line read from this LINE_READER.
Definition: richio.h:168
COMPONENT * GetComponent(unsigned aIndex)
Function GetComponent returns the COMPONENT at aIndex.
Definition: pcb_netlist.h:265
void Parse()
Function Parse parse the full netlist.
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:100
const char * name
Definition: DXF_plotter.cpp:61
size_t i
Definition: json11.cpp:597
void SetName(const wxString &aName)
Definition: pcb_netlist.h:145
void parseNet()
Function parseNet Parses a section like (net (code 20) (name /PC-A0) (node (ref BUS1) (pin 62)) (node...
void AddNet(const wxString &aPinName, const wxString &aNetName)
Definition: pcb_netlist.h:132
COMPONENT * GetComponentByReference(const wxString &aReference)
Function GetComponentByReference returns a COMPONENT by aReference.
int Parse(const UTF8 &aId, LIB_ID_TYPE aType, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:122