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 }
Class LINE_READER is an abstract class from which implementation specific LINE_READERs may be derived...
Definition: richio.h:81
bool IsLibSource(const wxString &aLibrary, const wxString &aName) const
Definition: pcb_netlist.h:193
virtual unsigned LineNumber() const
Function Line Number returns the line number of the last line read from this LINE_READER.
Definition: richio.h:159
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
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 ...
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.
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:139
void SetPinCount(int aPinCount)
Definition: pcb_netlist.h:179
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
unsigned Length() const
Function Length returns the number of bytes in the last line read from this LINE_READER.
Definition: richio.h:168
Class COMPONENT is used to store components and all of their related information found in a netlist...
Definition: pcb_netlist.h:83
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:92
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
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 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
unsigned GetCount() const
Function GetCount.
Definition: pcb_netlist.h:256