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
339  {
340  Expecting( "part or lib" );
341  }
342  }
343  break;
344 
345  case T_sheetpath:
346  while( ( token = NextTok() ) != T_tstamps );
347  NeedSYMBOLorNUMBER();
348  pathtimestamp = FROM_UTF8( CurText() );
349  NeedRIGHT();
350  NeedRIGHT();
351  break;
352 
353  case T_tstamp:
354  NeedSYMBOLorNUMBER();
355  timestamp = FROM_UTF8( CurText() );
356  NeedRIGHT();
357  break;
358 
359  default:
360  // Skip not used data (i.e all other tokens)
361  skipCurrent();
362  break;
363  }
364  }
365 
366  if( !footprint.IsEmpty() && fpid.Parse( footprint ) >= 0 )
367  {
368  wxString error;
369  error.Printf( _( "invalid footprint ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
370  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
371 
372  THROW_IO_ERROR( error );
373  }
374 
375  pathtimestamp += timestamp;
376  COMPONENT* component = new COMPONENT( fpid, ref, value, pathtimestamp );
377  component->SetName( name );
378  component->SetLibrary( library );
379  m_netlist->AddComponent( component );
380 }
381 
382 
384 {
385  /* Parses a section like
386  * (libpart (lib device) (part C)
387  * (aliases
388  * (alias Cxx)
389  * (alias Cyy))
390  * (description "Condensateur non polarise")
391  * (footprints
392  * (fp SM*)
393  * (fp C?)
394  * (fp C1-1))
395  * (fields
396  * (field (name Reference) C)
397  * (field (name Value) C))
398  * (pins
399  * (pin (num 1) (name ~) (type passive))
400  * (pin (num 2) (name ~) (type passive))))
401  *
402  * Currently footprints section/fp are read and data stored
403  * other fields (unused) are skipped
404  */
405  COMPONENT* component = NULL;
406  wxString libName;
407  wxString libPartName;
408  wxArrayString footprintFilters;
409  wxArrayString aliases;
410  int pinCount = 0;
411 
412  // The last token read was libpart, so read the next token
413  while( (token = NextTok()) != T_RIGHT )
414  {
415  if( token == T_LEFT )
416  token = NextTok();
417 
418  switch( token )
419  {
420  case T_lib:
421  NeedSYMBOLorNUMBER();
422  libName = FROM_UTF8( CurText() );
423  NeedRIGHT();
424  break;
425 
426  case T_part:
427  NeedSYMBOLorNUMBER();
428  libPartName = FROM_UTF8( CurText() );
429  NeedRIGHT();
430  break;
431 
432  case T_footprints:
433  // Read all fp elements (footprint filter item)
434  while( (token = NextTok()) != T_RIGHT )
435  {
436  if( token == T_LEFT )
437  token = NextTok();
438 
439  if( token != T_fp )
440  Expecting( T_fp );
441 
442  NeedSYMBOLorNUMBER();
443  footprintFilters.Add( FROM_UTF8( CurText() ) );
444  NeedRIGHT();
445  }
446  break;
447 
448  case T_aliases:
449  while( (token = NextTok()) != T_RIGHT )
450  {
451  if( token == T_LEFT )
452  token = NextTok();
453 
454  if( token != T_alias )
455  Expecting( T_alias );
456 
457  NeedSYMBOLorNUMBER();
458  aliases.Add( FROM_UTF8( CurText() ) );
459  NeedRIGHT();
460  }
461  break;
462 
463  case T_pins:
464  while( (token = NextTok()) != T_RIGHT )
465  {
466  if( token == T_LEFT )
467  token = NextTok();
468 
469  if( token != T_pin )
470  Expecting( T_pin );
471 
472  pinCount++;
473 
474  skipCurrent();
475  }
476  break;
477 
478  default:
479  // Skip not used data (i.e all other tokens)
480  skipCurrent();
481  break;
482  }
483  }
484 
485  // Find all of the components that reference this component library part definition.
486  for( unsigned i = 0; i < m_netlist->GetCount(); i++ )
487  {
488  component = m_netlist->GetComponent( i );
489 
490  if( component->IsLibSource( libName, libPartName ) )
491  {
492  component->SetFootprintFilters( footprintFilters );
493  component->SetPinCount( pinCount );
494  }
495 
496  for( unsigned jj = 0; jj < aliases.GetCount(); jj++ )
497  {
498  if( component->IsLibSource( libName, aliases[jj] ) )
499  {
500  component->SetFootprintFilters( footprintFilters );
501  component->SetPinCount( pinCount );
502  }
503  }
504 
505  }
506 }
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 ...
int Parse(const UTF8 &aId)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:122
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
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:133
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
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.
unsigned GetCount() const
Function GetCount.
Definition: pcb_netlist.h:256
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38