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 at end of file after parsing all sections
87 
88  while( ( token = NextTok() ) != T_EOF )
89  {
90  if( token == T_LEFT )
91  token = NextTok();
92 
93  switch( token )
94  {
95  case T_export: // The netlist starts here.
96  // nothing to do here, just increment the count of ')' to read at end of file
97  plevel++;
98  break;
99 
100  case T_version: // The netlist starts here.
101  // version id not yet used: read it but does not use it
102  NextTok();
103  NeedRIGHT();
104  break;
105 
106  case T_components: // The section comp starts here.
107  while( ( token = NextTok() ) != T_EOF )
108  {
109  if( token == T_RIGHT )
110  break;
111  else 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_EOF )
122  {
123  if( token == T_RIGHT )
124  break;
125  else if( token == T_LEFT )
126  token = NextTok();
127 
128  if( token == T_net ) // A net section if found. Read it
129  parseNet();
130  }
131 
132  break;
133 
134  case T_libparts: // The section libparts starts here.
135  while( ( token = NextTok() ) != T_EOF )
136  {
137  if( token == T_RIGHT )
138  break;
139  else if( token == T_LEFT )
140  token = NextTok();
141 
142  if( token == T_libpart ) // A libpart section if found. Read it
144  }
145 
146  break;
147 
148  case T_libraries: // The section libraries starts here.
149  // List of libraries in use.
150  // Not used here, just skip it
151  skipCurrent();
152  break;
153 
154  case T_design: // The section design starts here.
155  // Not used (mainly they are comments), just skip it
156  skipCurrent();
157  break;
158 
159  case T_RIGHT: // The closing parenthesis of the file.
160  plevel--;
161  break;
162 
163  default:
164  skipCurrent();
165  break;
166  }
167  }
168 
169  if( plevel != 0 )
170  {
171  wxLogDebug( wxT( "KICAD_NETLIST_PARSER::Parse(): bad parenthesis count (count = %d"),
172  plevel );
173  }
174 }
175 
176 
178 {
179  /* Parses a section like
180  * (net (code 20) (name /PC-A0)
181  * (node (ref BUS1) (pin 62))
182  * (node (ref U3) (pin 3))
183  * (node (ref U9) (pin M6)))
184  */
185 
186  COMPONENT* component = NULL;
187  wxString code;
188  wxString name;
189  wxString reference;
190  wxString pin;
191  int nodecount = 0;
192 
193  // The token net was read, so the next data is (code <number>)
194  while( (token = NextTok()) != T_EOF )
195  {
196  if( token == T_RIGHT )
197  break;
198  else if( token == T_LEFT )
199  token = NextTok();
200 
201  switch( token )
202  {
203  case T_code:
204  NeedSYMBOLorNUMBER();
205  code = FROM_UTF8( CurText() );
206  NeedRIGHT();
207  break;
208 
209  case T_name:
210  NeedSYMBOLorNUMBER();
211  name = FROM_UTF8( CurText() );
212  NeedRIGHT();
213 
214  if( name.IsEmpty() ) // Give a dummy net name like N-000109
215  name = wxT("N-00000") + code;
216 
217  break;
218 
219  case T_node:
220  while( (token = NextTok()) != T_EOF )
221  {
222  if( token == T_RIGHT )
223  break;
224  else if( token == T_LEFT )
225  token = NextTok();
226 
227  switch( token )
228  {
229  case T_ref:
230  NeedSYMBOLorNUMBER();
231  reference = FROM_UTF8( CurText() );
232  NeedRIGHT();
233  break;
234 
235  case T_pin:
236  NeedSYMBOLorNUMBER();
237  pin = FROM_UTF8( CurText() );
238  NeedRIGHT();
239  break;
240 
241  default:
242  skipCurrent();
243  break;
244  }
245  }
246 
247 
248  component = m_netlist->GetComponentByReference( reference );
249 
250  // Cannot happen if the netlist is valid.
251  if( component == NULL )
252  {
253  wxString msg;
254  msg.Printf( _( "Cannot find component with reference \"%s\" in netlist." ),
255  GetChars( reference ) );
258  }
259 
260  component->AddNet( pin, name );
261  nodecount++;
262  break;
263 
264  default:
265  skipCurrent();
266  break;
267  }
268  }
269 }
270 
271 
273 {
274  /* Parses a section like
275  * (comp (ref P1)
276  * (value DB25FEMELLE)
277  * (footprint DB25FC)
278  * (libsource (lib conn) (part DB25))
279  * (sheetpath (names /) (tstamps /))
280  * (tstamp 3256759C))
281  *
282  * other fields (unused) are skipped
283  * A component need a reference, value, footprint name and a full time stamp
284  * The full time stamp is the sheetpath time stamp + the component time stamp
285  */
286  LIB_ID fpid;
287  wxString footprint;
288  wxString ref;
289  wxString value;
290  wxString library;
291  wxString name;
292  wxString pathtimestamp, timestamp;
293 
294  // The token comp was read, so the next data is (ref P1)
295  while( (token = NextTok()) != T_RIGHT )
296  {
297  if( token == T_LEFT )
298  token = NextTok();
299 
300  switch( token )
301  {
302  case T_ref:
303  NeedSYMBOLorNUMBER();
304  ref = FROM_UTF8( CurText() );
305  NeedRIGHT();
306  break;
307 
308  case T_value:
309  NeedSYMBOLorNUMBER();
310  value = FROM_UTF8( CurText() );
311  NeedRIGHT();
312  break;
313 
314  case T_footprint:
315  NeedSYMBOLorNUMBER();
316  footprint = FromUTF8();
317  NeedRIGHT();
318  break;
319 
320  case T_libsource:
321  // Read libsource
322  while( (token = NextTok()) != T_RIGHT )
323  {
324  if( token == T_LEFT )
325  token = NextTok();
326 
327  if( token == T_lib )
328  {
329  NeedSYMBOLorNUMBER();
330  library = FROM_UTF8( CurText() );
331  NeedRIGHT();
332  }
333  else if( token == T_part )
334  {
335  NeedSYMBOLorNUMBER();
336  name = FROM_UTF8( CurText() );
337  NeedRIGHT();
338  }
339  else if( token == T_description )
340  {
341  NeedSYMBOLorNUMBER();
342  NeedRIGHT();
343  }
344  else
345  {
346  Expecting( "part, lib or description" );
347  }
348  }
349  break;
350 
351  case T_sheetpath:
352  while( ( token = NextTok() ) != T_EOF )
353  {
354  if( token == T_tstamps )
355  break;
356  }
357 
358  NeedSYMBOLorNUMBER();
359  pathtimestamp = FROM_UTF8( CurText() );
360  NeedRIGHT();
361  NeedRIGHT();
362  break;
363 
364  case T_tstamp:
365  NeedSYMBOLorNUMBER();
366  timestamp = FROM_UTF8( CurText() );
367  NeedRIGHT();
368  break;
369 
370  default:
371  // Skip not used data (i.e all other tokens)
372  skipCurrent();
373  break;
374  }
375  }
376 
377  if( !footprint.IsEmpty() && fpid.Parse( footprint, LIB_ID::ID_PCB, true ) >= 0 )
378  {
379  wxString error;
380  error.Printf( _( "Invalid footprint ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
381  CurSource(), CurLineNumber(), CurOffset() );
382 
383  THROW_IO_ERROR( error );
384  }
385 
386  pathtimestamp += timestamp;
387  COMPONENT* component = new COMPONENT( fpid, ref, value, pathtimestamp );
388  component->SetName( name );
389  component->SetLibrary( library );
390  m_netlist->AddComponent( component );
391 }
392 
393 
395 {
396  /* Parses a section like
397  * (libpart (lib device) (part C)
398  * (aliases
399  * (alias Cxx)
400  * (alias Cyy))
401  * (description "Condensateur non polarise")
402  * (footprints
403  * (fp SM*)
404  * (fp C?)
405  * (fp C1-1))
406  * (fields
407  * (field (name Reference) C)
408  * (field (name Value) C))
409  * (pins
410  * (pin (num 1) (name ~) (type passive))
411  * (pin (num 2) (name ~) (type passive))))
412  *
413  * Currently footprints section/fp are read and data stored
414  * other fields (unused) are skipped
415  */
416  COMPONENT* component = NULL;
417  wxString libName;
418  wxString libPartName;
419  wxArrayString footprintFilters;
420  wxArrayString aliases;
421  int pinCount = 0;
422 
423  // The last token read was libpart, so read the next token
424  while( (token = NextTok()) != T_RIGHT )
425  {
426  if( token == T_LEFT )
427  token = NextTok();
428 
429  switch( token )
430  {
431  case T_lib:
432  NeedSYMBOLorNUMBER();
433  libName = FROM_UTF8( CurText() );
434  NeedRIGHT();
435  break;
436 
437  case T_part:
438  NeedSYMBOLorNUMBER();
439  libPartName = FROM_UTF8( CurText() );
440  NeedRIGHT();
441  break;
442 
443  case T_footprints:
444  // Read all fp elements (footprint filter item)
445  while( (token = NextTok()) != T_RIGHT )
446  {
447  if( token == T_LEFT )
448  token = NextTok();
449 
450  if( token != T_fp )
451  Expecting( T_fp );
452 
453  NeedSYMBOLorNUMBER();
454  footprintFilters.Add( FROM_UTF8( CurText() ) );
455  NeedRIGHT();
456  }
457  break;
458 
459  case T_aliases:
460  while( (token = NextTok()) != T_RIGHT )
461  {
462  if( token == T_LEFT )
463  token = NextTok();
464 
465  if( token != T_alias )
466  Expecting( T_alias );
467 
468  NeedSYMBOLorNUMBER();
469  aliases.Add( FROM_UTF8( CurText() ) );
470  NeedRIGHT();
471  }
472  break;
473 
474  case T_pins:
475  while( (token = NextTok()) != T_RIGHT )
476  {
477  if( token == T_LEFT )
478  token = NextTok();
479 
480  if( token != T_pin )
481  Expecting( T_pin );
482 
483  pinCount++;
484 
485  skipCurrent();
486  }
487  break;
488 
489  default:
490  // Skip not used data (i.e all other tokens)
491  skipCurrent();
492  break;
493  }
494  }
495 
496  // Find all of the components that reference this component library part definition.
497  for( unsigned i = 0; i < m_netlist->GetCount(); i++ )
498  {
499  component = m_netlist->GetComponent( i );
500 
501  if( component->IsLibSource( libName, libPartName ) )
502  {
503  component->SetFootprintFilters( footprintFilters );
504  component->SetPinCount( pinCount );
505  }
506 
507  for( unsigned jj = 0; jj < aliases.GetCount(); jj++ )
508  {
509  if( component->IsLibSource( libName, aliases[jj] ) )
510  {
511  component->SetFootprintFilters( footprintFilters );
512  component->SetPinCount( pinCount );
513  }
514  }
515 
516  }
517 }
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:62
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)
#define _(s)
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:101
const char * name
Definition: DXF_plotter.cpp:61
size_t i
Definition: json11.cpp:649
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