KiCad PCB EDA Suite
fp_lib_table.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2010-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
5  * Copyright (C) 2012-2016 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 2012-2017 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 
27 #include <fctsys.h>
28 #include <common.h>
29 #include <kiface_i.h>
30 #include <footprint_info.h>
31 #include <lib_id.h>
32 #include <lib_table_lexer.h>
33 #include <fp_lib_table.h>
34 #include <class_module.h>
35 
36 #define OPT_SEP '|'
37 
38 using namespace LIB_TABLE_T;
39 
40 
41 static const wxChar global_tbl_name[] = wxT( "fp-lib-table" );
42 
43 
45 {
46  return LIB_TABLE_ROW::operator == ( aRow ) && type == aRow.type;
47 }
48 
49 
50 void FP_LIB_TABLE_ROW::SetType( const wxString& aType )
51 {
52  type = IO_MGR::EnumFromStr( aType );
53 
54  if( IO_MGR::PCB_FILE_T( -1 ) == type )
55  type = IO_MGR::KICAD;
56 }
57 
58 
60  LIB_TABLE( aFallBackTable )
61 {
62  // not copying fall back, simply search aFallBackTable separately
63  // if "nickName not found".
64 }
65 
66 
68 {
69  T tok;
70  wxString errMsg; // to collect error messages
71 
72  // This table may be nested within a larger s-expression, or not.
73  // Allow for parser of that optional containing s-epression to have looked ahead.
74  if( in->CurTok() != T_fp_lib_table )
75  {
76  in->NeedLEFT();
77 
78  if( ( tok = in->NextTok() ) != T_fp_lib_table )
80  }
81 
82  while( ( tok = in->NextTok() ) != T_RIGHT )
83  {
84  std::unique_ptr< FP_LIB_TABLE_ROW > row( new FP_LIB_TABLE_ROW );
85 
86  if( tok == T_EOF )
87  in->Expecting( T_RIGHT );
88 
89  if( tok != T_LEFT )
90  in->Expecting( T_LEFT );
91 
92  // in case there is a "row integrity" error, tell where later.
93  int lineNum = in->CurLineNumber();
94 
95  if( ( tok = in->NextTok() ) != T_lib )
96  in->Expecting( T_lib );
97 
98  // (name NICKNAME)
99  in->NeedLEFT();
100 
101  if( ( tok = in->NextTok() ) != T_name )
102  in->Expecting( T_name );
103 
104  in->NeedSYMBOLorNUMBER();
105 
106  row->SetNickName( in->FromUTF8() );
107 
108  in->NeedRIGHT();
109 
110  // After (name), remaining (lib) elements are order independent, and in
111  // some cases optional.
112  bool sawType = false;
113  bool sawOpts = false;
114  bool sawDesc = false;
115  bool sawUri = false;
116 
117  while( ( tok = in->NextTok() ) != T_RIGHT )
118  {
119  if( tok == T_EOF )
120  in->Unexpected( T_EOF );
121 
122  if( tok != T_LEFT )
123  in->Expecting( T_LEFT );
124 
125  tok = in->NeedSYMBOLorNUMBER();
126 
127  switch( tok )
128  {
129  case T_uri:
130  if( sawUri )
131  in->Duplicate( tok );
132  sawUri = true;
133  in->NeedSYMBOLorNUMBER();
134  row->SetFullURI( in->FromUTF8() );
135  break;
136 
137  case T_type:
138  if( sawType )
139  in->Duplicate( tok );
140  sawType = true;
141  in->NeedSYMBOLorNUMBER();
142  row->SetType( in->FromUTF8() );
143  break;
144 
145  case T_options:
146  if( sawOpts )
147  in->Duplicate( tok );
148  sawOpts = true;
149  in->NeedSYMBOLorNUMBER();
150  row->SetOptions( in->FromUTF8() );
151  break;
152 
153  case T_descr:
154  if( sawDesc )
155  in->Duplicate( tok );
156  sawDesc = true;
157  in->NeedSYMBOLorNUMBER();
158  row->SetDescr( in->FromUTF8() );
159  break;
160 
161  default:
162  in->Unexpected( tok );
163  }
164 
165  in->NeedRIGHT();
166  }
167 
168  if( !sawType )
169  in->Expecting( T_type );
170 
171  if( !sawUri )
172  in->Expecting( T_uri );
173 
174  // all nickNames within this table fragment must be unique, so we do not
175  // use doReplace in InsertRow(). (However a fallBack table can have a
176  // conflicting nickName and ours will supercede that one since in
177  // FindLib() we search this table before any fall back.)
178  wxString nickname = row->GetNickName(); // store it to be able to used it
179  // after row deletion if an error occurs
180  LIB_TABLE_ROW* tmp = row.release();
181 
182  if( !InsertRow( tmp ) )
183  {
184  delete tmp; // The table did not take ownership of the row.
185 
186  wxString msg = wxString::Format(
187  _( "Duplicate library nickname '%s' found in footprint library "
188  "table file line %d" ), GetChars( nickname ), lineNum );
189 
190  if( !errMsg.IsEmpty() )
191  errMsg << '\n';
192 
193  errMsg << msg;
194  }
195  }
196 
197  if( !errMsg.IsEmpty() )
198  THROW_IO_ERROR( errMsg );
199 }
200 
201 
202 bool FP_LIB_TABLE::operator==( const FP_LIB_TABLE& aFpTable ) const
203 {
204  if( rows.size() == aFpTable.rows.size() )
205  {
206  for( unsigned i = 0; i < rows.size(); ++i )
207  {
208  if( (FP_LIB_TABLE_ROW&)rows[i] != (FP_LIB_TABLE_ROW&)aFpTable.rows[i] )
209  return false;
210  }
211 
212  return true;
213  }
214 
215  return false;
216 }
217 
218 
219 void FP_LIB_TABLE::Format( OUTPUTFORMATTER* aOutput, int aIndentLevel ) const
220 {
221  aOutput->Print( aIndentLevel, "(fp_lib_table\n" );
222 
223  for( LIB_TABLE_ROWS_CITER it = rows.begin(); it != rows.end(); ++it )
224  it->Format( aOutput, aIndentLevel+1 );
225 
226  aOutput->Print( aIndentLevel, ")\n" );
227 }
228 
229 
230 void FP_LIB_TABLE::FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aNickname )
231 {
232  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
233  wxASSERT( (PLUGIN*) row->plugin );
234  row->plugin->FootprintEnumerate( aFootprintNames, row->GetFullURI( true ),
235  row->GetProperties() );
236 }
237 
238 
239 void FP_LIB_TABLE::PrefetchLib( const wxString& aNickname )
240 {
241  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
242  wxASSERT( (PLUGIN*) row->plugin );
243  row->plugin->PrefetchLib( row->GetFullURI( true ), row->GetProperties() );
244 }
245 
246 
247 const FP_LIB_TABLE_ROW* FP_LIB_TABLE::FindRow( const wxString& aNickname )
248 {
249  FP_LIB_TABLE_ROW* row = dynamic_cast< FP_LIB_TABLE_ROW* >( findRow( aNickname ) );
250 
251  if( !row )
252  {
253  wxString msg = wxString::Format(
254  _( "fp-lib-table files contain no library with nickname '%s'" ),
255  GetChars( aNickname ) );
256 
257  THROW_IO_ERROR( msg );
258  }
259 
260  // We've been 'lazy' up until now, but it cannot be deferred any longer,
261  // instantiate a PLUGIN of the proper kind if it is not already in this
262  // FP_LIB_TABLE_ROW.
263  if( !row->plugin )
264  row->setPlugin( IO_MGR::PluginFind( row->type ) );
265 
266  return row;
267 }
268 
269 
270 MODULE* FP_LIB_TABLE::FootprintLoad( const wxString& aNickname, const wxString& aFootprintName )
271 {
272  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
273  wxASSERT( (PLUGIN*) row->plugin );
274 
275  MODULE* ret = row->plugin->FootprintLoad( row->GetFullURI( true ), aFootprintName,
276  row->GetProperties() );
277 
278  // The library cannot know its own name, because it might have been renamed or moved.
279  // Therefore footprints cannot know their own library nickname when residing in
280  // a footprint library.
281  // Only at this API layer can we tell the footprint about its actual library nickname.
282  if( ret )
283  {
284  // remove "const"-ness, I really do want to set nickname without
285  // having to copy the LIB_ID and its two strings, twice each.
286  LIB_ID& fpid = (LIB_ID&) ret->GetFPID();
287 
288  // Catch any misbehaving plugin, which should be setting internal footprint name properly:
289  wxASSERT( aFootprintName == fpid.GetLibItemName().wx_str() );
290 
291  // and clearing nickname
292  wxASSERT( !fpid.GetLibNickname().size() );
293 
294  fpid.SetLibNickname( row->GetNickName() );
295  }
296 
297  return ret;
298 }
299 
300 
302  const MODULE* aFootprint, bool aOverwrite )
303 {
304  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
305  wxASSERT( (PLUGIN*) row->plugin );
306 
307  if( !aOverwrite )
308  {
309  // Try loading the footprint to see if it already exists, caller wants overwrite
310  // protection, which is atypical, not the default.
311 
312  wxString fpname = aFootprint->GetFPID().GetLibItemName();
313 
314  std::unique_ptr<MODULE> footprint( row->plugin->FootprintLoad( row->GetFullURI( true ),
315  fpname, row->GetProperties() ) );
316 
317  if( footprint.get() )
318  return SAVE_SKIPPED;
319  }
320 
321  row->plugin->FootprintSave( row->GetFullURI( true ), aFootprint, row->GetProperties() );
322 
323  return SAVE_OK;
324 }
325 
326 
327 void FP_LIB_TABLE::FootprintDelete( const wxString& aNickname, const wxString& aFootprintName )
328 {
329  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
330  wxASSERT( (PLUGIN*) row->plugin );
331  return row->plugin->FootprintDelete( row->GetFullURI( true ), aFootprintName,
332  row->GetProperties() );
333 }
334 
335 
336 bool FP_LIB_TABLE::IsFootprintLibWritable( const wxString& aNickname )
337 {
338  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
339  wxASSERT( (PLUGIN*) row->plugin );
340  return row->plugin->IsFootprintLibWritable( row->GetFullURI( true ) );
341 }
342 
343 
344 void FP_LIB_TABLE::FootprintLibDelete( const wxString& aNickname )
345 {
346  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
347  wxASSERT( (PLUGIN*) row->plugin );
348  row->plugin->FootprintLibDelete( row->GetFullURI( true ), row->GetProperties() );
349 }
350 
351 
352 void FP_LIB_TABLE::FootprintLibCreate( const wxString& aNickname )
353 {
354  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
355  wxASSERT( (PLUGIN*) row->plugin );
356  row->plugin->FootprintLibCreate( row->GetFullURI( true ), row->GetProperties() );
357 }
358 
359 
361 {
362  wxString nickname = aFootprintId.GetLibNickname();
363  wxString fpname = aFootprintId.GetLibItemName();
364 
365  if( nickname.size() )
366  {
367  return FootprintLoad( nickname, fpname );
368  }
369 
370  // nickname is empty, sequentially search (alphabetically) all libs/nicks for first match:
371  else
372  {
373  std::vector<wxString> nicks = GetLogicalLibs();
374 
375  // Search each library going through libraries alphabetically.
376  for( unsigned i = 0; i < nicks.size(); ++i )
377  {
378  // FootprintLoad() returns NULL on not found, does not throw exception
379  // unless there's an IO_ERROR.
380  MODULE* ret = FootprintLoad( nicks[i], fpname );
381 
382  if( ret )
383  return ret;
384  }
385 
386  return NULL;
387  }
388 }
389 
390 
392 {
393  return "KISYSMOD";
394 }
395 
396 
398 {
399  bool tableExists = true;
400  wxFileName fn = GetGlobalTableFileName();
401 
402  if( !fn.FileExists() )
403  {
404  tableExists = false;
405 
406  if( !fn.DirExists() && !fn.Mkdir( 0x777, wxPATH_MKDIR_FULL ) )
407  {
408  THROW_IO_ERROR( wxString::Format( _( "Cannot create global library table path '%s'." ),
409  GetChars( fn.GetPath() ) ) );
410  }
411 
412  // Attempt to copy the default global file table from the KiCad
413  // template folder to the user's home configuration path.
414  wxString fileName = Kiface().KifaceSearch().FindValidPath( global_tbl_name );
415 
416  // The fallback is to create an empty global footprint table for the user to populate.
417  if( fileName.IsEmpty() || !::wxCopyFile( fileName, fn.GetFullPath(), false ) )
418  {
419  FP_LIB_TABLE emptyTable;
420 
421  emptyTable.Save( fn.GetFullPath() );
422  }
423  }
424 
425  aTable.Load( fn.GetFullPath() );
426 
427  return tableExists;
428 }
429 
430 
432 {
433  wxFileName fn;
434 
435  fn.SetPath( GetKicadConfigPath() );
436  fn.SetName( global_tbl_name );
437 
438  return fn.GetFullPath();
439 }
void setPlugin(PLUGIN *aPlugin)
Definition: fp_lib_table.h:93
static const wxChar global_tbl_name[]
bool IsFootprintLibWritable(const wxString &aNickname)
Function IsFootprintLibWritable.
LIB_TABLE_T::T CurTok()
Function CurTok returns whatever NextTok() returned the last time it was called.
Class LIB_TABLE_ROW.
virtual void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, const PROPERTIES *aProperties=NULL)
Return a list of footprint names contained within the library at aLibraryPath.
Definition: plugin.cpp:61
virtual void PrefetchLib(const wxString &aLibraryPath, const PROPERTIES *aProperties=NULL)
Function PrefetchLib If possible, prefetches the specified library (e.g.
Definition: plugin.cpp:69
Class FP_LIB_TABLE_ROW.
Definition: fp_lib_table.h:42
const PROPERTIES * GetProperties() const
Function GetProperties.
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Function InsertRow.
T
enum T contains all this lexer's tokens.
MODULE * FootprintLoad(const wxString &aNickname, const wxString &aFootprintName)
Function FootprintLoad.
virtual void FootprintSave(const wxString &aLibraryPath, const MODULE *aFootprint, const PROPERTIES *aProperties=NULL)
Function FootprintSave will write aModule to an existing library located at aLibraryPath.
Definition: plugin.cpp:85
FP_LIB_TABLE(FP_LIB_TABLE *aFallBackTable=NULL)
Constructor FP_LIB_TABLE.
void Unexpected(int aTok)
Function Unexpected throws an IO_ERROR exception with an input file specific error message...
Definition: dsnlexer.cpp:369
Class OUTPUTFORMATTER is an important interface (abstract class) used to output 8 bit text in a conve...
Definition: richio.h:327
bool operator==(const FP_LIB_TABLE &aFpTable) const
LIB_TABLE_ROWS rows
std::string::size_type size() const
Definition: utf8.h:115
Class LIB_ID.
Definition: lib_id.h:56
void FootprintLibDelete(const wxString &aNickname)
wxString FromUTF8()
Function FromUTF8 returns the current token text as a wxString, assuming that the input byte stream i...
Definition: dsnlexer.h:498
const wxString GetFullURI(bool aSubstituted=false) const
Function GetFullURI.
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
PLUGIN::RELEASER plugin
Definition: fp_lib_table.h:98
virtual bool IsFootprintLibWritable(const wxString &aLibraryPath)
Function IsFootprintLibWritable returns true iff the library at aLibraryPath is writable.
Definition: plugin.cpp:114
const LIB_ID & GetFPID() const
Definition: class_module.h:164
SEARCH_STACK & KifaceSearch()
Only for DSO specific 'non-library' files.
Definition: kiface_i.h:127
void NeedLEFT()
Function NeedLEFT calls NextTok() and then verifies that the token read in is a DSN_LEFT.
Definition: dsnlexer.cpp:393
wxString wx_str() const
Definition: utf8.cpp:48
static const wxString GlobalPathEnvVariableName()
Function GlobalPathEnvVarVariableName.
virtual void Parse(LIB_TABLE_LEXER *aLexer) override
Function Parse.
virtual MODULE * FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, const PROPERTIES *aProperties=NULL)
Function FootprintLoad loads a footprint having aFootprintName from the aLibraryPath containing a lib...
Definition: plugin.cpp:76
static bool LoadGlobalTable(FP_LIB_TABLE &aTable)
Function LoadGlobalTable loads the global footprint library table into aTable.
LIB_TABLE_T::T NeedSYMBOLorNUMBER()
Function NeedSYMBOLorNUMBER calls NextTok() and then verifies that the token read in satisfies bool I...
virtual bool FootprintLibDelete(const wxString &aLibraryPath, const PROPERTIES *aProperties=NULL)
Function FootprintLibDelete deletes an existing footprint library and returns true, or if library does not exist returns false, or throws an exception if library exists but is read only or cannot be deleted for some other reason.
Definition: plugin.cpp:106
static PCB_FILE_T EnumFromStr(const wxString &aFileType)
Function EnumFromStr returns the PCB_FILE_T from the corresponding plugin type name: "kicad"...
Definition: io_mgr.cpp:137
const UTF8 & GetLibItemName() const
Function GetLibItemName.
Definition: lib_id.h:129
S-expression Pcbnew file format.
Definition: io_mgr.h:54
void PrefetchLib(const wxString &aNickname)
Function PrefetchLib If possible, prefetches the specified library (e.g.
bool operator==(const LIB_TABLE_ROW &r) const
void Save(const wxString &aFileName) const
Function Save.
bool operator==(const FP_LIB_TABLE_ROW &aRow) const
LIB_TABLE_ROW * findRow(const wxString &aNickname) const
Function findRow returns a LIB_TABLE_ROW if aNickname is found in this table or in any chained fallBa...
void Expecting(int aTok)
Function Expecting throws an IO_ERROR exception with an input file specific error message...
Definition: dsnlexer.cpp:353
void Load(const wxString &aFileName)
Function Load.
wxString GetKicadConfigPath()
Function GetKicadConfigPath.
Definition: common.cpp:217
virtual void Format(OUTPUTFORMATTER *aOutput, int aIndentLevel) const override
Generate the table in s-expression format to aOutput with an indention level of aIndentLevel.
int SetLibNickname(const UTF8 &aNickname)
Function SetLibNickname.
Definition: lib_id.cpp:219
void FootprintLibCreate(const wxString &aNickname)
const FP_LIB_TABLE_ROW * FindRow(const wxString &aNickName)
Function FindRow.
SAVE_T
Enum SAVE_T is the set of return values from FootprintSave() below.
Definition: fp_lib_table.h:187
const wxString & GetNickName() const
Function GetNickName.
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
LIB_TABLE_ROWS::const_iterator LIB_TABLE_ROWS_CITER
LIB_TABLE_T::T NextTok()
Function NextTok returns the next token found in the input file or T_EOF when reaching the end of fil...
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void Duplicate(int aTok)
Function Duplicate throws an IO_ERROR exception with a message saying specifically that aTok is a dup...
Definition: dsnlexer.cpp:377
static PLUGIN * PluginFind(PCB_FILE_T aFileType)
Function PluginFind returns a PLUGIN which the caller can use to import, export, save, or load design documents.
Definition: io_mgr.cpp:58
Class PLUGIN is a base class that BOARD loading and saving plugins should derive from.
Definition: io_mgr.h:193
virtual void FootprintDelete(const wxString &aLibraryPath, const wxString &aFootprintName, const PROPERTIES *aProperties=NULL)
Function FootprintDelete deletes aFootprintName from the library at aLibraryPath. ...
Definition: plugin.cpp:92
int CurLineNumber()
Function CurLineNumber returns the current line number within my LINE_READER.
Definition: dsnlexer.h:507
The common library.
virtual void FootprintLibCreate(const wxString &aLibraryPath, const PROPERTIES *aProperties=NULL)
Function FootprintLibCreate creates a new empty footprint library at aLibraryPath empty...
Definition: plugin.cpp:99
void NeedRIGHT()
Function NeedRIGHT calls NextTok() and then verifies that the token read in is a DSN_RIGHT.
Definition: dsnlexer.cpp:401
Class LIB_TABLE_LEXER is an automatically generated class using the TokenList2DnsLexer.cmake technology, based on keywords provided by file: /home/kicad/workspace/kicad-doxygen/common/lib_table.keywords.
MODULE * FootprintLoadWithOptionalNickname(const LIB_ID &aFootprintId)
Function FootprintLoadWithOptionalNickname loads a footprint having aFootprintId with possibly an emp...
wxString FindValidPath(const wxString &aFileName) const
Definition: search_stack.h:71
Module description (excepted pads)
void SetType(const wxString &aType) override
Function SetType.
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Function Print formats and writes text to the output stream.
Definition: richio.cpp:408
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aNickname)
Return a list of footprint names contained within the library given by aNickname. ...
const UTF8 & GetLibNickname() const
Function GetLibNickname.
Definition: lib_id.h:108
SAVE_T FootprintSave(const wxString &aNickname, const MODULE *aFootprint, bool aOverwrite=true)
Function FootprintSave.
void FootprintDelete(const wxString &aNickname, const wxString &aFootprintName)
Function FootprintDelete.
PCB_FILE_T
Enum PCB_FILE_T is a set of file types that the IO_MGR knows about, and for which there has been a pl...
Definition: io_mgr.h:51
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
static wxString GetGlobalTableFileName()
Function GetGlobalTableFileName.
std::vector< wxString > GetLogicalLibs()
Function GetLogicalLibs.
C++ does not put enum values in separate namespaces unless the enum itself is in a separate namespace...
Class LIB_TABLE.