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 <macros.h>
30 #include <kiface_i.h>
31 #include <footprint_info.h>
32 #include <lib_id.h>
33 #include <lib_table_lexer.h>
34 #include <fp_lib_table.h>
35 #include <class_module.h>
36 
37 #define OPT_SEP '|'
38 
39 using namespace LIB_TABLE_T;
40 
41 
42 static const wxChar global_tbl_name[] = wxT( "fp-lib-table" );
43 
44 
46 {
47  return LIB_TABLE_ROW::operator == ( aRow ) && type == aRow.type;
48 }
49 
50 
51 void FP_LIB_TABLE_ROW::SetType( const wxString& aType )
52 {
53  type = IO_MGR::EnumFromStr( aType );
54 
55  if( IO_MGR::PCB_FILE_T( -1 ) == type )
56  type = IO_MGR::KICAD;
57 }
58 
59 
61  LIB_TABLE( aFallBackTable )
62 {
63  // not copying fall back, simply search aFallBackTable separately
64  // if "nickName not found".
65 }
66 
67 
69 {
70  T tok;
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  if( ( tok = in->NextTok() ) != T_fp_lib_table )
79  }
80 
81  while( ( tok = in->NextTok() ) != T_RIGHT )
82  {
83  std::unique_ptr< FP_LIB_TABLE_ROW > row( new FP_LIB_TABLE_ROW );
84 
85  if( tok == T_EOF )
86  in->Expecting( T_RIGHT );
87 
88  if( tok != T_LEFT )
89  in->Expecting( T_LEFT );
90 
91  // in case there is a "row integrity" error, tell where later.
92  int lineNum = in->CurLineNumber();
93  int offset = in->CurOffset();
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  if( !InsertRow( row.release() ) )
179  {
180  wxString msg = wxString::Format(
181  _( "'%s' is a duplicate footprint library nickName" ),
182  GetChars( row->GetNickName() ) );
183  THROW_PARSE_ERROR( msg, in->CurSource(), in->CurLine(), lineNum, offset );
184  }
185  }
186 }
187 
188 
189 void FP_LIB_TABLE::Format( OUTPUTFORMATTER* aOutput, int aIndentLevel ) const
190 {
191  aOutput->Print( aIndentLevel, "(fp_lib_table\n" );
192 
193  for( LIB_TABLE_ROWS_CITER it = rows.begin(); it != rows.end(); ++it )
194  it->Format( aOutput, aIndentLevel+1 );
195 
196  aOutput->Print( aIndentLevel, ")\n" );
197 }
198 
199 
200 wxArrayString FP_LIB_TABLE::FootprintEnumerate( const wxString& aNickname )
201 {
202  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
203  wxASSERT( (PLUGIN*) row->plugin );
204  return row->plugin->FootprintEnumerate( row->GetFullURI( true ), row->GetProperties() );
205 }
206 
207 
208 void FP_LIB_TABLE::PrefetchLib( const wxString& aNickname )
209 {
210  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
211  wxASSERT( (PLUGIN*) row->plugin );
212  row->plugin->PrefetchLib( row->GetFullURI( true ), row->GetProperties() );
213 }
214 
215 
216 const FP_LIB_TABLE_ROW* FP_LIB_TABLE::FindRow( const wxString& aNickname )
217  throw( IO_ERROR )
218 {
219  FP_LIB_TABLE_ROW* row = dynamic_cast< FP_LIB_TABLE_ROW* >( findRow( aNickname ) );
220 
221  if( !row )
222  {
223  wxString msg = wxString::Format(
224  _( "fp-lib-table files contain no library with nickname '%s'" ),
225  GetChars( aNickname ) );
226 
227  THROW_IO_ERROR( msg );
228  }
229 
230  // We've been 'lazy' up until now, but it cannot be deferred any longer,
231  // instantiate a PLUGIN of the proper kind if it is not already in this
232  // FP_LIB_TABLE_ROW.
233  if( !row->plugin )
234  row->setPlugin( IO_MGR::PluginFind( row->type ) );
235 
236  return row;
237 }
238 
239 
240 MODULE* FP_LIB_TABLE::FootprintLoad( const wxString& aNickname, const wxString& aFootprintName )
241 {
242  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
243  wxASSERT( (PLUGIN*) row->plugin );
244 
245  MODULE* ret = row->plugin->FootprintLoad( row->GetFullURI( true ), aFootprintName,
246  row->GetProperties() );
247 
248  // The library cannot know its own name, because it might have been renamed or moved.
249  // Therefore footprints cannot know their own library nickname when residing in
250  // a footprint library.
251  // Only at this API layer can we tell the footprint about its actual library nickname.
252  if( ret )
253  {
254  // remove "const"-ness, I really do want to set nickname without
255  // having to copy the LIB_ID and its two strings, twice each.
256  LIB_ID& fpid = (LIB_ID&) ret->GetFPID();
257 
258  // Catch any misbehaving plugin, which should be setting internal footprint name properly:
259  wxASSERT( aFootprintName == FROM_UTF8( fpid.GetLibItemName() ) );
260 
261  // and clearing nickname
262  wxASSERT( !fpid.GetLibNickname().size() );
263 
264  fpid.SetLibNickname( TO_UTF8( row->GetNickName() ) );
265  }
266 
267  return ret;
268 }
269 
270 
272  const MODULE* aFootprint, bool aOverwrite )
273 {
274  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
275  wxASSERT( (PLUGIN*) row->plugin );
276 
277  if( !aOverwrite )
278  {
279  // Try loading the footprint to see if it already exists, caller wants overwrite
280  // protection, which is atypical, not the default.
281 
282  wxString fpname = FROM_UTF8( aFootprint->GetFPID().GetLibItemName() );
283 
284  std::unique_ptr<MODULE> footprint( row->plugin->FootprintLoad( row->GetFullURI( true ),
285  fpname, row->GetProperties() ) );
286 
287  if( footprint.get() )
288  return SAVE_SKIPPED;
289  }
290 
291  row->plugin->FootprintSave( row->GetFullURI( true ), aFootprint, row->GetProperties() );
292 
293  return SAVE_OK;
294 }
295 
296 
297 void FP_LIB_TABLE::FootprintDelete( const wxString& aNickname, const wxString& aFootprintName )
298 {
299  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
300  wxASSERT( (PLUGIN*) row->plugin );
301  return row->plugin->FootprintDelete( row->GetFullURI( true ), aFootprintName,
302  row->GetProperties() );
303 }
304 
305 
306 bool FP_LIB_TABLE::IsFootprintLibWritable( const wxString& aNickname )
307 {
308  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
309  wxASSERT( (PLUGIN*) row->plugin );
310  return row->plugin->IsFootprintLibWritable( row->GetFullURI( true ) );
311 }
312 
313 
314 void FP_LIB_TABLE::FootprintLibDelete( const wxString& aNickname )
315 {
316  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
317  wxASSERT( (PLUGIN*) row->plugin );
318  row->plugin->FootprintLibDelete( row->GetFullURI( true ), row->GetProperties() );
319 }
320 
321 
322 void FP_LIB_TABLE::FootprintLibCreate( const wxString& aNickname )
323 {
324  const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
325  wxASSERT( (PLUGIN*) row->plugin );
326  row->plugin->FootprintLibCreate( row->GetFullURI( true ), row->GetProperties() );
327 }
328 
329 
331  throw( IO_ERROR, PARSE_ERROR, boost::interprocess::lock_exception )
332 {
333  wxString nickname = FROM_UTF8( aFootprintId.GetLibNickname() );
334  wxString fpname = FROM_UTF8( aFootprintId.GetLibItemName() );
335 
336  if( nickname.size() )
337  {
338  return FootprintLoad( nickname, fpname );
339  }
340 
341  // nickname is empty, sequentially search (alphabetically) all libs/nicks for first match:
342  else
343  {
344  std::vector<wxString> nicks = GetLogicalLibs();
345 
346  // Search each library going through libraries alphabetically.
347  for( unsigned i = 0; i < nicks.size(); ++i )
348  {
349  // FootprintLoad() returns NULL on not found, does not throw exception
350  // unless there's an IO_ERROR.
351  MODULE* ret = FootprintLoad( nicks[i], fpname );
352 
353  if( ret )
354  return ret;
355  }
356 
357  return NULL;
358  }
359 }
360 
361 
363 {
364  return "KISYSMOD";
365 }
366 
367 
369  throw (IO_ERROR, PARSE_ERROR, boost::interprocess::lock_exception )
370 {
371  bool tableExists = true;
372  wxFileName fn = GetGlobalTableFileName();
373 
374  if( !fn.FileExists() )
375  {
376  tableExists = false;
377 
378  if( !fn.DirExists() && !fn.Mkdir( 0x777, wxPATH_MKDIR_FULL ) )
379  {
380  THROW_IO_ERROR( wxString::Format( _( "Cannot create global library table path '%s'." ),
381  GetChars( fn.GetPath() ) ) );
382  }
383 
384  // Attempt to copy the default global file table from the KiCad
385  // template folder to the user's home configuration path.
386  wxString fileName = Kiface().KifaceSearch().FindValidPath( global_tbl_name );
387 
388  // The fallback is to create an empty global footprint table for the user to populate.
389  if( fileName.IsEmpty() || !::wxCopyFile( fileName, fn.GetFullPath(), false ) )
390  {
391  FP_LIB_TABLE emptyTable;
392 
393  emptyTable.Save( fn.GetFullPath() );
394  }
395  }
396 
397  aTable.Load( fn.GetFullPath() );
398 
399  return tableExists;
400 }
401 
402 
404 {
405  wxFileName fn;
406 
407  fn.SetPath( GetKicadConfigPath() );
408  fn.SetName( global_tbl_name );
409 
410  return fn.GetFullPath();
411 }
void setPlugin(PLUGIN *aPlugin)
Definition: fp_lib_table.h:92
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.
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
virtual void PrefetchLib(const wxString &aLibraryPath, const PROPERTIES *aProperties=NULL)
Function PrefetchLib If possible, prefetches the specified library (e.g.
Definition: plugin.cpp:69
LIB_TABLE_ROWS::const_iterator LIB_TABLE_ROWS_CITER
Class FP_LIB_TABLE_ROW.
Definition: fp_lib_table.h:41
const PROPERTIES * GetProperties() const
Function GetProperties.
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Function InsertRow.
wxArrayString FootprintEnumerate(const wxString &aNickname)
Function FootprintEnumerate returns a list of footprint names contained within the library given by a...
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:370
Class OUTPUTFORMATTER is an important interface (abstract class) used to output 8 bit text in a conve...
Definition: richio.h:327
LIB_TABLE_ROWS rows
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
This file contains miscellaneous commonly used macros and functions.
PLUGIN::RELEASER plugin
Definition: fp_lib_table.h:97
const wxString & CurSource()
Function CurFilename returns the current LINE_READER source.
Definition: dsnlexer.h:528
virtual wxArrayString FootprintEnumerate(const wxString &aLibraryPath, const PROPERTIES *aProperties=NULL)
Function FootprintEnumerate returns a list of footprint names contained within the library at aLibrar...
Definition: plugin.cpp:61
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:151
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
SEARCH_STACK & KifaceSearch()
Only for DSO specific 'non-library' files.
Definition: kiface_i.h:125
void NeedLEFT()
Function NeedLEFT calls NextTok() and then verifies that the token read in is a DSN_LEFT.
Definition: dsnlexer.cpp:394
static const wxString GlobalPathEnvVariableName()
Function GlobalPathEnvVarVariableName.
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:133
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
int CurOffset()
Function CurOffset returns the byte offset within the current line, using a 1 based index...
Definition: dsnlexer.h:538
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.
#define THROW_IO_ERROR(x)
Definition: utf8.cpp:60
bool operator==(const FP_LIB_TABLE_ROW &aRow) const
void Expecting(int aTok)
Function Expecting throws an IO_ERROR exception with an input file specific error message...
Definition: dsnlexer.cpp:354
wxString GetKicadConfigPath()
Function GetKicadConfigPath.
Definition: common.cpp:217
virtual void Format(OUTPUTFORMATTER *aOutput, int aIndentLevel) const override
Function Format.
int SetLibNickname(const UTF8 &aNickname)
Function SetLibNickname.
Definition: lib_id.cpp:219
const char * CurLine()
Function CurLine returns the current line of text, from which the CurText() would return its token...
Definition: dsnlexer.h:517
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:181
const wxString & GetNickName() const
Function GetNickName.
Struct PARSE_ERROR contains a filename or source description, a problem input line, a line number, a byte offset, and an error message which contains the the caller's report and his call site information: CPP source file, function, and line number.
Definition: ki_exception.h:94
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_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:378
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:402
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
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
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:47
static wxString GetGlobalTableFileName()
Function GetGlobalTableFileName.
C++ does not put enum values in separate namespaces unless the enum itself is in a separate namespace...
Class LIB_TABLE.