KiCad PCB EDA Suite
symbol_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) 2016 Wayne Stambaugh <stambaughw@gmail.com>
5  * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 
26 #include <lib_id.h>
27 #include <lib_table_lexer.h>
28 #include <pgm_base.h>
29 #include <search_stack.h>
31 #include <systemdirsappend.h>
32 #include <symbol_lib_table.h>
33 #include <lib_symbol.h>
34 
35 #define OPT_SEP '|'
36 
37 using namespace LIB_TABLE_T;
38 
39 
40 static const wxString global_tbl_name( "sym-lib-table" );
41 
42 
43 const char* SYMBOL_LIB_TABLE::PropPowerSymsOnly = "pwr_sym_only";
44 const char* SYMBOL_LIB_TABLE::PropNonPowerSymsOnly = "non_pwr_sym_only";
45 int SYMBOL_LIB_TABLE::m_modifyHash = 1; // starts at 1 and goes up
46 
47 
52 
53 
55 {
56  return LIB_TABLE_ROW::operator == ( aRow ) && type == aRow.type;
57 }
58 
59 
60 void SYMBOL_LIB_TABLE_ROW::SetType( const wxString& aType )
61 {
62  type = SCH_IO_MGR::EnumFromStr( aType );
63 
64  if( SCH_IO_MGR::SCH_FILE_T( -1 ) == type )
65  type = SCH_IO_MGR::SCH_LEGACY;
66 
67  plugin.release();
68 }
69 
70 
72 {
73  if( !plugin )
74  {
75  wxArrayString dummyList;
76 
77  plugin.set( SCH_IO_MGR::FindPlugin( type ) );
78  SetLoaded( false );
79  plugin->EnumerateSymbolLib( dummyList, GetFullURI( true ), GetProperties() );
80  SetLoaded( true );
81  return true;
82  }
83 
84  return false;
85 }
86 
87 
89  LIB_TABLE( aFallBackTable )
90 {
91  // not copying fall back, simply search aFallBackTable separately
92  // if "nickName not found".
93 }
94 
95 
97 {
98  return g_symbolLibraryTable;
99 }
100 
101 
102 void SYMBOL_LIB_TABLE::Parse( LIB_TABLE_LEXER* in )
103 {
104  T tok;
105  wxString errMsg; // to collect error messages
106 
107  // This table may be nested within a larger s-expression, or not.
108  // Allow for parser of that optional containing s-epression to have looked ahead.
109  if( in->CurTok() != T_sym_lib_table )
110  {
111  in->NeedLEFT();
112 
113  if( ( tok = in->NextTok() ) != T_sym_lib_table )
114  in->Expecting( T_sym_lib_table );
115  }
116 
117  while( ( tok = in->NextTok() ) != T_RIGHT )
118  {
119  std::unique_ptr< SYMBOL_LIB_TABLE_ROW > row = std::make_unique<SYMBOL_LIB_TABLE_ROW>();
120 
121  if( tok == T_EOF )
122  in->Expecting( T_RIGHT );
123 
124  if( tok != T_LEFT )
125  in->Expecting( T_LEFT );
126 
127  // in case there is a "row integrity" error, tell where later.
128  int lineNum = in->CurLineNumber();
129 
130  if( ( tok = in->NextTok() ) != T_lib )
131  in->Expecting( T_lib );
132 
133  // (name NICKNAME)
134  in->NeedLEFT();
135 
136  if( ( tok = in->NextTok() ) != T_name )
137  in->Expecting( T_name );
138 
139  in->NeedSYMBOLorNUMBER();
140 
141  row->SetNickName( in->FromUTF8() );
142 
143  in->NeedRIGHT();
144 
145  // After (name), remaining (lib) elements are order independent, and in
146  // some cases optional.
147  bool sawType = false;
148  bool sawOpts = false;
149  bool sawDesc = false;
150  bool sawUri = false;
151  bool sawDisabled = false;
152 
153  while( ( tok = in->NextTok() ) != T_RIGHT )
154  {
155  if( tok == T_EOF )
156  in->Unexpected( T_EOF );
157 
158  if( tok != T_LEFT )
159  in->Expecting( T_LEFT );
160 
161  tok = in->NeedSYMBOLorNUMBER();
162 
163  switch( tok )
164  {
165  case T_uri:
166  if( sawUri )
167  in->Duplicate( tok );
168  sawUri = true;
169  in->NeedSYMBOLorNUMBER();
170  row->SetFullURI( in->FromUTF8() );
171  break;
172 
173  case T_type:
174  if( sawType )
175  in->Duplicate( tok );
176  sawType = true;
177  in->NeedSYMBOLorNUMBER();
178  row->SetType( in->FromUTF8() );
179  break;
180 
181  case T_options:
182  if( sawOpts )
183  in->Duplicate( tok );
184  sawOpts = true;
185  in->NeedSYMBOLorNUMBER();
186  row->SetOptions( in->FromUTF8() );
187  break;
188 
189  case T_descr:
190  if( sawDesc )
191  in->Duplicate( tok );
192  sawDesc = true;
193  in->NeedSYMBOLorNUMBER();
194  row->SetDescr( in->FromUTF8() );
195  break;
196 
197  case T_disabled:
198  if( sawDisabled )
199  in->Duplicate( tok );
200  sawDisabled = true;
201  row->SetEnabled( false );
202  break;
203 
204  default:
205  in->Unexpected( tok );
206  }
207 
208  in->NeedRIGHT();
209  }
210 
211  if( !sawType )
212  in->Expecting( T_type );
213 
214  if( !sawUri )
215  in->Expecting( T_uri );
216 
217  // all nickNames within this table fragment must be unique, so we do not
218  // use doReplace in InsertRow(). (However a fallBack table can have a
219  // conflicting nickName and ours will supercede that one since in
220  // FindLib() we search this table before any fall back.)
221  wxString nickname = row->GetNickName(); // store it to be able to used it
222  // after row deletion if an error occurs
223  LIB_TABLE_ROW* tmp = row.release();
224 
225  if( !InsertRow( tmp ) )
226  {
227  delete tmp; // The table did not take ownership of the row.
228 
229  wxString msg = wxString::Format( _( "Duplicate library nickname '%s' found in symbol "
230  "library table file line %d" ),
231  nickname,
232  lineNum );
233 
234  if( !errMsg.IsEmpty() )
235  errMsg << '\n';
236 
237  errMsg << msg;
238  }
239  }
240 
241  if( !errMsg.IsEmpty() )
242  THROW_IO_ERROR( errMsg );
243 }
244 
245 
246 void SYMBOL_LIB_TABLE::Format( OUTPUTFORMATTER* aOutput, int aIndentLevel ) const
247 {
248  aOutput->Print( aIndentLevel, "(sym_lib_table\n" );
249 
250  for( LIB_TABLE_ROWS_CITER it = rows.begin(); it != rows.end(); ++it )
251  {
252  it->Format( aOutput, aIndentLevel+1 );
253  }
254 
255  aOutput->Print( aIndentLevel, ")\n" );
256 }
257 
258 
260 {
261  int hash = 0;
262  std::vector< wxString > libNames = GetLogicalLibs();
263 
264  for( const auto& libName : libNames )
265  {
266  const SYMBOL_LIB_TABLE_ROW* row = FindRow( libName, true );
267 
268  if( !row || !row->plugin )
269  {
270  wxFAIL;
271  continue;
272  }
273 
274  hash += row->plugin->GetModifyHash();
275  }
276 
277  hash += m_modifyHash;
278 
279  return hash;
280 }
281 
282 
283 void SYMBOL_LIB_TABLE::EnumerateSymbolLib( const wxString& aNickname, wxArrayString& aAliasNames,
284  bool aPowerSymbolsOnly )
285 {
286  SYMBOL_LIB_TABLE_ROW* row = FindRow( aNickname, true );
287  wxCHECK( row && row->plugin, /* void */ );
288 
289  wxString options = row->GetOptions();
290 
291  if( aPowerSymbolsOnly )
292  row->SetOptions( row->GetOptions() + " " + PropPowerSymsOnly );
293 
294  row->SetLoaded( false );
295  row->plugin->EnumerateSymbolLib( aAliasNames, row->GetFullURI( true ), row->GetProperties() );
296  row->SetLoaded( true );
297 
298  if( aPowerSymbolsOnly )
299  row->SetOptions( options );
300 }
301 
302 
303 SYMBOL_LIB_TABLE_ROW* SYMBOL_LIB_TABLE::FindRow( const wxString& aNickname, bool aCheckIfEnabled )
304 {
305  SYMBOL_LIB_TABLE_ROW* row =
306  dynamic_cast< SYMBOL_LIB_TABLE_ROW* >( findRow( aNickname, aCheckIfEnabled ) );
307 
308  if( !row )
309  return nullptr;
310 
311  // We've been 'lazy' up until now, but it cannot be deferred any longer,
312  // instantiate a PLUGIN of the proper kind if it is not already in this
313  // SYMBOL_LIB_TABLE_ROW.
314  if( !row->plugin )
315  row->setPlugin( SCH_IO_MGR::FindPlugin( row->type ) );
316 
317  return row;
318 }
319 
320 
321 void SYMBOL_LIB_TABLE::LoadSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
322  const wxString& aNickname, bool aPowerSymbolsOnly )
323 {
324  SYMBOL_LIB_TABLE_ROW* row = FindRow( aNickname, true );
325  wxCHECK( row && row->plugin, /* void */ );
326 
327  wxString options = row->GetOptions();
328 
329  if( aPowerSymbolsOnly )
330  row->SetOptions( row->GetOptions() + " " + PropPowerSymsOnly );
331 
332  row->SetLoaded( false );
333  row->plugin->EnumerateSymbolLib( aSymbolList, row->GetFullURI( true ), row->GetProperties() );
334  row->SetLoaded( true );
335 
336  if( aPowerSymbolsOnly )
337  row->SetOptions( options );
338 
339  // The library cannot know its own name, because it might have been renamed or moved.
340  // Therefore footprints cannot know their own library nickname when residing in
341  // a symbol library.
342  // Only at this API layer can we tell the symbol about its actual library nickname.
343  for( LIB_SYMBOL* symbol : aSymbolList )
344  {
345  LIB_ID id = symbol->GetLibId();
346 
347  id.SetLibNickname( row->GetNickName() );
348  symbol->SetLibId( id );
349  }
350 }
351 
352 
353 LIB_SYMBOL* SYMBOL_LIB_TABLE::LoadSymbol( const wxString& aNickname, const wxString& aSymbolName )
354 {
355  SYMBOL_LIB_TABLE_ROW* row = FindRow( aNickname, true );
356 
357  if( !row || !row->plugin )
358  return nullptr;
359 
360  LIB_SYMBOL* symbol = row->plugin->LoadSymbol( row->GetFullURI( true ), aSymbolName,
361  row->GetProperties() );
362 
363  if( symbol == nullptr )
364  return symbol;
365 
366  // The library cannot know its own name, because it might have been renamed or moved.
367  // Therefore footprints cannot know their own library nickname when residing in
368  // a symbol library.
369  // Only at this API layer can we tell the symbol about its actual library nickname.
370  if( symbol )
371  {
372  LIB_ID id = symbol->GetLibId();
373 
374  id.SetLibNickname( row->GetNickName() );
375  symbol->SetLibId( id );
376  }
377 
378  return symbol;
379 }
380 
381 
383  const LIB_SYMBOL* aSymbol, bool aOverwrite )
384 {
385  const SYMBOL_LIB_TABLE_ROW* row = FindRow( aNickname, true );
386  wxCHECK( row && row->plugin, SAVE_SKIPPED );
387 
388  if( !row->plugin->IsSymbolLibWritable( row->GetFullURI( true ) ) )
389  return SAVE_SKIPPED;
390 
391  if( !aOverwrite )
392  {
393  // Try loading the footprint to see if it already exists, caller wants overwrite
394  // protection, which is atypical, not the default.
395 
396  wxString name = aSymbol->GetLibId().GetLibItemName();
397 
398  std::unique_ptr< LIB_SYMBOL > symbol( row->plugin->LoadSymbol( row->GetFullURI( true ),
399  name,
400  row->GetProperties() ) );
401 
402  if( symbol.get() )
403  return SAVE_SKIPPED;
404  }
405 
406  try
407  {
408  row->plugin->SaveSymbol( row->GetFullURI( true ), aSymbol, row->GetProperties() );
409  }
410  catch( const IO_ERROR& )
411  {
412  return SAVE_SKIPPED;
413  }
414 
415  return SAVE_OK;
416 }
417 
418 
419 void SYMBOL_LIB_TABLE::DeleteSymbol( const wxString& aNickname, const wxString& aSymbolName )
420 {
421  const SYMBOL_LIB_TABLE_ROW* row = FindRow( aNickname, true );
422  wxCHECK( row && row->plugin, /* void */ );
423  return row->plugin->DeleteSymbol( row->GetFullURI( true ), aSymbolName,
424  row->GetProperties() );
425 }
426 
427 
428 bool SYMBOL_LIB_TABLE::IsSymbolLibWritable( const wxString& aNickname )
429 {
430  const SYMBOL_LIB_TABLE_ROW* row = FindRow( aNickname, true );
431  wxCHECK( row && row->plugin, false );
432  return row->plugin->IsSymbolLibWritable( row->GetFullURI( true ) );
433 }
434 
435 bool SYMBOL_LIB_TABLE::IsSymbolLibLoaded( const wxString& aNickname )
436 {
437  const SYMBOL_LIB_TABLE_ROW* row = FindRow( aNickname, true );
438  wxCHECK( row, false );
439  return row->GetIsLoaded();
440 }
441 
442 
443 void SYMBOL_LIB_TABLE::DeleteSymbolLib( const wxString& aNickname )
444 {
445  const SYMBOL_LIB_TABLE_ROW* row = FindRow( aNickname, true );
446  wxCHECK( row && row->plugin, /* void */ );
447  row->plugin->DeleteSymbolLib( row->GetFullURI( true ), row->GetProperties() );
448 }
449 
450 
451 void SYMBOL_LIB_TABLE::CreateSymbolLib( const wxString& aNickname )
452 {
453  const SYMBOL_LIB_TABLE_ROW* row = FindRow( aNickname, true );
454  wxCHECK( row && row->plugin, /* void */ );
455  row->plugin->CreateSymbolLib( row->GetFullURI( true ), row->GetProperties() );
456 }
457 
458 
460 {
461  wxString nickname = aLibId.GetLibNickname();
462  wxString name = aLibId.GetLibItemName();
463 
464  if( nickname.size() )
465  {
466  return LoadSymbol( nickname, name );
467  }
468 
469  // nickname is empty, sequentially search (alphabetically) all libs/nicks for first match:
470  else
471  {
472  std::vector<wxString> nicks = GetLogicalLibs();
473 
474  // Search each library going through libraries alphabetically.
475  for( unsigned i = 0; i < nicks.size(); ++i )
476  {
477  // FootprintLoad() returns NULL on not found, does not throw exception
478  // unless there's an IO_ERROR.
479  LIB_SYMBOL* ret = LoadSymbol( nicks[i], name );
480 
481  if( ret )
482  return ret;
483  }
484 
485  return nullptr;
486  }
487 }
488 
489 
491 {
492  return "KICAD6_SYMBOL_DIR";
493 }
494 
495 
497 {
498  bool tableExists = true;
499  wxFileName fn = GetGlobalTableFileName();
500 
501  if( !fn.FileExists() )
502  {
503  tableExists = false;
504 
505  if( !fn.DirExists() && !fn.Mkdir( 0x777, wxPATH_MKDIR_FULL ) )
506  {
507  THROW_IO_ERROR( wxString::Format( _( "Cannot create global library table path '%s'." ),
508  fn.GetPath() ) );
509  }
510 
511  // Attempt to copy the default global file table from the KiCad
512  // template folder to the user's home configuration path.
513  SEARCH_STACK ss;
514 
515  SystemDirsAppend( &ss );
516 
517  wxString templatePath =
518  Pgm().GetLocalEnvVariables().at( wxT( "KICAD6_TEMPLATE_DIR" ) ).GetValue();
519 
520  if( !templatePath.IsEmpty() )
521  ss.AddPaths( templatePath, 0 );
522 
523  wxString fileName = ss.FindValidPath( global_tbl_name );
524 
525  // The fallback is to create an empty global symbol table for the user to populate.
526  if( fileName.IsEmpty() || !::wxCopyFile( fileName, fn.GetFullPath(), false ) )
527  {
528  SYMBOL_LIB_TABLE emptyTable;
529 
530  emptyTable.Save( fn.GetFullPath() );
531  }
532  }
533 
534  aTable.Load( fn.GetFullPath() );
535 
536  return tableExists;
537 }
538 
539 
541 {
542  wxFileName fn;
543 
545  fn.SetName( global_tbl_name );
546 
547  return fn.GetFullPath();
548 }
549 
550 
552 {
553  return global_tbl_name;
554 }
static const wxString & GetSymbolLibTableFileName()
static SYMBOL_LIB_TABLE & GetGlobalLibTable()
void EnumerateSymbolLib(const wxString &aNickname, wxArrayString &aAliasNames, bool aPowerSymbolsOnly=false)
Return a list of symbol alias names contained within the library given by aNickname.
wxString FindValidPath(const wxString &aFileName) const
Definition: search_stack.h:70
const UTF8 & GetLibItemName() const
Definition: lib_id.h:104
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_PLUGIN obje...
const wxString & GetOptions() const
Return the options string, which may hold a password or anything else needed to instantiate the under...
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
void CreateSymbolLib(const wxString &aNickname)
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
SCH_PLUGIN::SCH_PLUGIN_RELEASER plugin
SAVE_T SaveSymbol(const wxString &aNickname, const LIB_SYMBOL *aSymbol, bool aOverwrite=true)
Write aSymbol to an existing library given by aNickname.
void DeleteSymbolLib(const wxString &aNickname)
void SetType(const wxString &aType) override
Change the schematic plugin type represented by this row.
static const wxString GlobalPathEnvVariableName()
Return the name of the environment variable used to hold the directory of locally installed "KiCad sp...
System directories search utilities.
An interface used to output 8 bit text in a convenient way.
Definition: richio.h:309
LIB_SYMBOL * LoadSymbolWithOptionalNickname(const LIB_ID &aId)
Load a LIB_SYMBOL having aFootprintId with possibly an empty library nickname.
Look for files in a number of paths.
Definition: search_stack.h:41
LIB_TABLE_ROWS rows
static const wxString global_tbl_name("sym-lib-table")
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
bool IsSymbolLibWritable(const wxString &aNickname)
Return true if the library given by aNickname is writable.
Define a library symbol object.
Definition: lib_symbol.h:96
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
bool operator==(const LIB_TABLE_ROW &r) const
bool GetIsLoaded() const
bool IsSymbolLibLoaded(const wxString &aNickname)
Return true if the library given by aNickname was successfully loaded.
bool operator==(const SYMBOL_LIB_TABLE_ROW &aRow) const
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
void SetLoaded(bool aLoaded)
Mark the row as being a loaded library.
const wxString & GetNickName() const
static bool LoadGlobalTable(SYMBOL_LIB_TABLE &aTable)
Load the global symbol library table into aTable.
LIB_ID GetLibId() const override
Definition: lib_symbol.h:135
bool Refresh()
Attempt to reload the library.
#define _(s)
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:90
void SystemDirsAppend(SEARCH_STACK *aSearchStack)
Append system places to aSearchStack in a platform specific way and pertinent to KiCad programs.
LIB_TABLE_ROW * findRow(const wxString &aNickname, bool aCheckIfEnabled=false) const
Return a LIB_TABLE_ROW if aNickname is found in this table or in any chained fallBack table fragment,...
virtual void Format(OUTPUTFORMATTER *aOutput, int aIndentLevel) const override
Generate the table in s-expression format to aOutput with an indentation level of aIndentLevel.
void SetLibId(const LIB_ID &aLibId)
Definition: lib_symbol.h:136
void setPlugin(SCH_PLUGIN *aPlugin)
void Load(const wxString &aFileName)
Load the library table using the path defined by aFileName aFallBackTable.
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:97
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
void LoadSymbolLib(std::vector< LIB_SYMBOL * > &aAliasList, const wxString &aNickname, bool aPowerSymbolsOnly=false)
see class PGM_BASE
LIB_TABLE_ROWS::const_iterator LIB_TABLE_ROWS_CITER
const char * name
Definition: DXF_plotter.cpp:59
void DeleteSymbol(const wxString &aNickname, const wxString &aSymbolName)
Deletes the aSymbolName from the library given by aNickname.
static SCH_FILE_T EnumFromStr(const wxString &aFileType)
Return the #SCH_FILE_T from the corresponding plugin type name: "kicad", "legacy",...
Definition: sch_io_mgr.cpp:98
static int m_modifyHash
helper for GetModifyHash()
virtual void Parse(LIB_TABLE_LEXER *aLexer) override
Parse the #LIB_TABLE_LEXER s-expression library table format into the appropriate LIB_TABLE_ROW objec...
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
void SetOptions(const wxString &aOptions)
Change the library options strings.
SAVE_T
The set of return values from SaveSymbol() below.
static const char * PropNonPowerSymsOnly
const PROPERTIES * GetProperties() const
Return the constant PROPERTIES for this library (LIB_TABLE_ROW).
SYMBOL_LIB_TABLE g_symbolLibraryTable
The global symbol library table.
SYMBOL_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an SYMBOL_LIB_TABLE_ROW if aNickName is found in this table or in any chained fallBack table f...
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition: richio.cpp:426
SYMBOL_LIB_TABLE(SYMBOL_LIB_TABLE *aFallBackTable=nullptr)
Build a symbol library table by pre-pending this table fragment in front of aFallBackTable.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
static wxString GetGlobalTableFileName()
Fetch the global symbol library table file name.
static const char * PropPowerSymsOnly
void AddPaths(const wxString &aPaths, int aIndex=-1)
Insert or append path(s).
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.
Manage LIB_TABLE_ROW records (rows), and can be searched based on library nickname.