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") (pin_function "clock"))
183  * (node (ref "U9") (pin "M6") (pin_function "reset")))
184  */
185 
186  COMPONENT* component = NULL;
187  wxString code;
188  wxString name;
189  wxString reference;
190  wxString pin_number;
191  wxString pin_function;
192  int nodecount = 0;
193 
194  // The token net was read, so the next data is (code <number>)
195  while( (token = NextTok()) != T_EOF )
196  {
197  if( token == T_RIGHT )
198  break;
199  else 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  pin_function.Clear(); // By default: no pin function.
222 
223  while( (token = NextTok()) != T_EOF )
224  {
225  if( token == T_RIGHT )
226  break;
227  else if( token == T_LEFT )
228  token = NextTok();
229 
230  switch( token )
231  {
232  case T_ref:
233  NeedSYMBOLorNUMBER();
234  reference = FROM_UTF8( CurText() );
235  NeedRIGHT();
236  break;
237 
238  case T_pin:
239  NeedSYMBOLorNUMBER();
240  pin_number = FROM_UTF8( CurText() );
241  NeedRIGHT();
242  break;
243 
244  case T_pinfunction:
245  NeedSYMBOLorNUMBER();
246  pin_function = FROM_UTF8( CurText() );
247  NeedRIGHT();
248  break;
249 
250  default:
251  skipCurrent();
252  break;
253  }
254  }
255 
256 
257  component = m_netlist->GetComponentByReference( reference );
258 
259  // Cannot happen if the netlist is valid.
260  if( component == NULL )
261  {
262  wxString msg;
263  msg.Printf( _( "Cannot find component with reference \"%s\" in netlist." ),
264  GetChars( reference ) );
267  }
268 
269  component->AddNet( pin_number, name, pin_function );
270  nodecount++;
271  break;
272 
273  default:
274  skipCurrent();
275  break;
276  }
277  }
278 }
279 
280 
282 {
283  /* Parses a section like
284  * (comp (ref P1)
285  * (value DB25FEMELLE)
286  * (footprint DB25FC)
287  * (libsource (lib conn) (part DB25))
288  * (sheetpath (names /) (tstamps /))
289  * (tstamp 3256759C))
290  *
291  * other fields (unused) are skipped
292  * A component need a reference, value, footprint name and a full time stamp
293  * The full time stamp is the sheetpath time stamp + the component time stamp
294  */
295  LIB_ID fpid;
296  wxString footprint;
297  wxString ref;
298  wxString value;
299  wxString library;
300  wxString name;
301  wxString pathtimestamp, timestamp;
302 
303  // The token comp was read, so the next data is (ref P1)
304  while( (token = NextTok()) != T_RIGHT )
305  {
306  if( token == T_LEFT )
307  token = NextTok();
308 
309  switch( token )
310  {
311  case T_ref:
312  NeedSYMBOLorNUMBER();
313  ref = FROM_UTF8( CurText() );
314  NeedRIGHT();
315  break;
316 
317  case T_value:
318  NeedSYMBOLorNUMBER();
319  value = FROM_UTF8( CurText() );
320  NeedRIGHT();
321  break;
322 
323  case T_footprint:
324  NeedSYMBOLorNUMBER();
325  footprint = FromUTF8();
326  NeedRIGHT();
327  break;
328 
329  case T_libsource:
330  // Read libsource
331  while( (token = NextTok()) != T_RIGHT )
332  {
333  if( token == T_LEFT )
334  token = NextTok();
335 
336  if( token == T_lib )
337  {
338  NeedSYMBOLorNUMBER();
339  library = FROM_UTF8( CurText() );
340  NeedRIGHT();
341  }
342  else if( token == T_part )
343  {
344  NeedSYMBOLorNUMBER();
345  name = FROM_UTF8( CurText() );
346  NeedRIGHT();
347  }
348  else if( token == T_description )
349  {
350  NeedSYMBOLorNUMBER();
351  NeedRIGHT();
352  }
353  else
354  {
355  Expecting( "part, lib or description" );
356  }
357  }
358  break;
359 
360  case T_sheetpath:
361  while( ( token = NextTok() ) != T_EOF )
362  {
363  if( token == T_tstamps )
364  break;
365  }
366 
367  NeedSYMBOLorNUMBER();
368  pathtimestamp = FROM_UTF8( CurText() );
369  NeedRIGHT();
370  NeedRIGHT();
371  break;
372 
373  case T_tstamp:
374  NeedSYMBOLorNUMBER();
375  timestamp = FROM_UTF8( CurText() );
376  NeedRIGHT();
377  break;
378 
379  default:
380  // Skip not used data (i.e all other tokens)
381  skipCurrent();
382  break;
383  }
384  }
385 
386  if( !footprint.IsEmpty() && fpid.Parse( footprint, LIB_ID::ID_PCB, true ) >= 0 )
387  {
388  wxString error;
389  error.Printf( _( "Invalid footprint ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
390  CurSource(), CurLineNumber(), CurOffset() );
391 
392  THROW_IO_ERROR( error );
393  }
394 
395  pathtimestamp += timestamp;
396  COMPONENT* component = new COMPONENT( fpid, ref, value, pathtimestamp );
397  component->SetName( name );
398  component->SetLibrary( library );
399  m_netlist->AddComponent( component );
400 }
401 
402 
404 {
405  /* Parses a section like
406  * (libpart (lib device) (part C)
407  * (aliases
408  * (alias Cxx)
409  * (alias Cyy))
410  * (description "Condensateur non polarise")
411  * (footprints
412  * (fp SM*)
413  * (fp C?)
414  * (fp C1-1))
415  * (fields
416  * (field (name Reference) C)
417  * (field (name Value) C))
418  * (pins
419  * (pin (num 1) (name ~) (type passive))
420  * (pin (num 2) (name ~) (type passive))))
421  *
422  * Currently footprints section/fp are read and data stored
423  * other fields (unused) are skipped
424  */
425  COMPONENT* component = NULL;
426  wxString libName;
427  wxString libPartName;
428  wxArrayString footprintFilters;
429  wxArrayString aliases;
430  int pinCount = 0;
431 
432  // The last token read was libpart, so read the next token
433  while( (token = NextTok()) != T_RIGHT )
434  {
435  if( token == T_LEFT )
436  token = NextTok();
437 
438  switch( token )
439  {
440  case T_lib:
441  NeedSYMBOLorNUMBER();
442  libName = FROM_UTF8( CurText() );
443  NeedRIGHT();
444  break;
445 
446  case T_part:
447  NeedSYMBOLorNUMBER();
448  libPartName = FROM_UTF8( CurText() );
449  NeedRIGHT();
450  break;
451 
452  case T_footprints:
453  // Read all fp elements (footprint filter item)
454  while( (token = NextTok()) != T_RIGHT )
455  {
456  if( token == T_LEFT )
457  token = NextTok();
458 
459  if( token != T_fp )
460  Expecting( T_fp );
461 
462  NeedSYMBOLorNUMBER();
463  footprintFilters.Add( FROM_UTF8( CurText() ) );
464  NeedRIGHT();
465  }
466  break;
467 
468  case T_aliases:
469  while( (token = NextTok()) != T_RIGHT )
470  {
471  if( token == T_LEFT )
472  token = NextTok();
473 
474  if( token != T_alias )
475  Expecting( T_alias );
476 
477  NeedSYMBOLorNUMBER();
478  aliases.Add( FROM_UTF8( CurText() ) );
479  NeedRIGHT();
480  }
481  break;
482 
483  case T_pins:
484  while( (token = NextTok()) != T_RIGHT )
485  {
486  if( token == T_LEFT )
487  token = NextTok();
488 
489  if( token != T_pin )
490  Expecting( T_pin );
491 
492  pinCount++;
493 
494  skipCurrent();
495  }
496  break;
497 
498  default:
499  // Skip not used data (i.e all other tokens)
500  skipCurrent();
501  break;
502  }
503  }
504 
505  // Find all of the components that reference this component library part definition.
506  for( unsigned i = 0; i < m_netlist->GetCount(); i++ )
507  {
508  component = m_netlist->GetComponent( i );
509 
510  if( component->IsLibSource( libName, libPartName ) )
511  {
512  component->SetFootprintFilters( footprintFilters );
513  component->SetPinCount( pinCount );
514  }
515 
516  for( unsigned jj = 0; jj < aliases.GetCount(); jj++ )
517  {
518  if( component->IsLibSource( libName, aliases[jj] ) )
519  {
520  component->SetFootprintFilters( footprintFilters );
521  component->SetPinCount( pinCount );
522  }
523  }
524 
525  }
526 }
bool IsLibSource(const wxString &aLibrary, const wxString &aName) const
Definition: pcb_netlist.h:196
LINE_READER is an abstract class from which implementation specific LINE_READERs may be derived to re...
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:151
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:259
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:175
void parseLibPartList()
Function parseLibPartList reads the section "libparts" in the netlist: (libparts (libpart (lib device...
NETLIST stores all of information read from a netlist along with the flags used to update the NETLIST...
Definition: pcb_netlist.h:217
#define NULL
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:182
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
COMPONENT is used to store components and all of their related information found in a netlist.
Definition: pcb_netlist.h:85
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:268
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:60
#define _(s)
Definition: 3d_actions.cpp:31
void SetName(const wxString &aName)
Definition: pcb_netlist.h:148
void parseNet()
Function parseNet Parses a section like (net (code 20) (name /PC-A0) (node (ref BUS1) (pin 62)) (node...
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
void AddNet(const wxString &aPinName, const wxString &aNetName, const wxString &aPinFunction)
Definition: pcb_netlist.h:135