implement most of SCH::LIB_TABLE, start SCH::LPID, enhance richio
This commit is contained in:
parent
5b5db5557d
commit
a7c11a0b11
|
@ -65,7 +65,7 @@ DSNLEXER::DSNLEXER( const KEYWORD* aKeywordTable, unsigned aKeywordCount,
|
||||||
keywords( aKeywordTable ),
|
keywords( aKeywordTable ),
|
||||||
keywordCount( aKeywordCount )
|
keywordCount( aKeywordCount )
|
||||||
{
|
{
|
||||||
FILE_LINE_READER* fileReader = new FILE_LINE_READER( aFile, aFilename, 4096 );
|
FILE_LINE_READER* fileReader = new FILE_LINE_READER( aFile, aFilename );
|
||||||
PushReader( fileReader );
|
PushReader( fileReader );
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,11 +82,23 @@ void LINE_READER::expandCapacity( unsigned newsize )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FILE_LINE_READER::FILE_LINE_READER( FILE* aFile, const wxString& aFileName, unsigned aMaxLineLength ) :
|
FILE_LINE_READER::FILE_LINE_READER( FILE* aFile, const wxString& aFileName,
|
||||||
|
bool doOwn,
|
||||||
|
unsigned aStartingLineNumber,
|
||||||
|
unsigned aMaxLineLength ) :
|
||||||
LINE_READER( aMaxLineLength ),
|
LINE_READER( aMaxLineLength ),
|
||||||
|
iOwn( doOwn ),
|
||||||
fp( aFile )
|
fp( aFile )
|
||||||
{
|
{
|
||||||
source = aFileName;
|
source = aFileName;
|
||||||
|
lineNum = aStartingLineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FILE_LINE_READER::~FILE_LINE_READER()
|
||||||
|
{
|
||||||
|
if( iOwn && fp )
|
||||||
|
fclose( fp );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,6 +129,29 @@ unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
STRING_LINE_READER::STRING_LINE_READER( const std::string& aString, const wxString& aSource ) :
|
||||||
|
LINE_READER( LINE_READER_LINE_DEFAULT_MAX ),
|
||||||
|
lines( aString ),
|
||||||
|
ndx( 0 )
|
||||||
|
{
|
||||||
|
// Clipboard text should be nice and _use multiple lines_ so that
|
||||||
|
// we can report _line number_ oriented error messages when parsing.
|
||||||
|
source = aSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
STRING_LINE_READER::STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint ) :
|
||||||
|
LINE_READER( LINE_READER_LINE_DEFAULT_MAX ),
|
||||||
|
lines( aStartingPoint.lines ),
|
||||||
|
ndx( aStartingPoint.ndx )
|
||||||
|
{
|
||||||
|
// since we are keeping the same "source" name, for error reporting purposes
|
||||||
|
// we need to have the same notion of line number and offset.
|
||||||
|
|
||||||
|
source = aStartingPoint.source;
|
||||||
|
lineNum = aStartingPoint.lineNum;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR )
|
unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR )
|
||||||
{
|
{
|
||||||
size_t nlOffset = lines.find( '\n', ndx );
|
size_t nlOffset = lines.find( '\n', ndx );
|
||||||
|
|
|
@ -53,7 +53,7 @@ class LINE_READER
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
unsigned length; ///< no. bytes in line before trailing nul.
|
unsigned length; ///< no. bytes in line before trailing nul.
|
||||||
int lineNum;
|
unsigned lineNum;
|
||||||
|
|
||||||
char* line; ///< the read line of UTF8 text
|
char* line; ///< the read line of UTF8 text
|
||||||
unsigned capacity; ///< no. bytes allocated for line.
|
unsigned capacity; ///< no. bytes allocated for line.
|
||||||
|
@ -115,7 +115,7 @@ public:
|
||||||
* returns the line number of the last line read from this LINE_READER. Lines
|
* returns the line number of the last line read from this LINE_READER. Lines
|
||||||
* start from 1.
|
* start from 1.
|
||||||
*/
|
*/
|
||||||
int LineNumber() const
|
unsigned LineNumber() const
|
||||||
{
|
{
|
||||||
return lineNum;
|
return lineNum;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,8 @@ class FILE_LINE_READER : public LINE_READER
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
FILE* fp; ///< I own this file
|
bool iOwn; ///< if I own the file, I'll promise to close it, else not.
|
||||||
|
FILE* fp; ///< I may own this file, but might not.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -151,15 +152,23 @@ public:
|
||||||
*
|
*
|
||||||
* @param aFile is an open file.
|
* @param aFile is an open file.
|
||||||
* @param aFileName is the name of the file for error reporting purposes.
|
* @param aFileName is the name of the file for error reporting purposes.
|
||||||
|
* @param doOwn if true, means I should close the open file, else not.
|
||||||
|
* @param aStartingLineNumber is the initial line number to report on error, and is
|
||||||
|
* accessible here for the case where multiple DSNLEXERs are reading from the
|
||||||
|
* same file in sequence, all from the same open file (with @a doOwn = false).
|
||||||
|
* Internally it is incremented by one after each ReadLine(), so the first
|
||||||
|
* reported line number will always be one greater than what is provided here.
|
||||||
* @param aMaxLineLength is the number of bytes to use in the line buffer.
|
* @param aMaxLineLength is the number of bytes to use in the line buffer.
|
||||||
*/
|
*/
|
||||||
FILE_LINE_READER( FILE* aFile, const wxString& aFileName, unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX );
|
FILE_LINE_READER( FILE* aFile, const wxString& aFileName, bool doOwn = true,
|
||||||
|
unsigned aStartingLineNumber = 0,
|
||||||
|
unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX );
|
||||||
|
|
||||||
~FILE_LINE_READER()
|
/**
|
||||||
{
|
* Destructor
|
||||||
if( fp )
|
* may or may not close the open file, depending on @a doOwn in constructor.
|
||||||
fclose( fp );
|
*/
|
||||||
}
|
~FILE_LINE_READER();
|
||||||
|
|
||||||
unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description
|
unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description
|
||||||
|
|
||||||
|
@ -198,17 +207,17 @@ public:
|
||||||
* @param aSource describes the source of aString for error reporting purposes
|
* @param aSource describes the source of aString for error reporting purposes
|
||||||
* can be anything meaninful, such as wxT( "clipboard" ).
|
* can be anything meaninful, such as wxT( "clipboard" ).
|
||||||
*/
|
*/
|
||||||
STRING_LINE_READER( const std::string& aString, const wxString& aSource ) :
|
STRING_LINE_READER( const std::string& aString, const wxString& aSource );
|
||||||
LINE_READER( LINE_READER_LINE_DEFAULT_MAX ),
|
|
||||||
lines( aString ),
|
|
||||||
ndx( 0 )
|
|
||||||
{
|
|
||||||
// Clipboard text should be nice and _use multiple lines_ so that
|
|
||||||
// we can report _line number_ oriented error messages when parsing.
|
|
||||||
source = aSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description
|
/**
|
||||||
|
* Constructor STRING_LINE_READER( const STRING_LINE_READER& )
|
||||||
|
* allows for a continuation of the reading of a stream started by another
|
||||||
|
* STRING_LINE_READER. Any stream offset and source name are used from
|
||||||
|
* @a aStartingPoint.
|
||||||
|
*/
|
||||||
|
STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint );
|
||||||
|
|
||||||
|
unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
152
new/design.h
152
new/design.h
|
@ -371,158 +371,6 @@ const STRING StrEmpty = "";
|
||||||
/** @} exception_types Exception Types */
|
/** @} exception_types Exception Types */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class LPID (aka GUID)
|
|
||||||
* is a Logical Part ID and consists of various portions much like a URI. It
|
|
||||||
* relies heavily on a logical library name to hide where actual physical library
|
|
||||||
* sources reside. Its static functions serve as managers of the "library table" to
|
|
||||||
* map logical library names to actual library sources.
|
|
||||||
* <p>
|
|
||||||
* Example LPID string:
|
|
||||||
* "kicad:passives/R/rev6".
|
|
||||||
* <p>
|
|
||||||
* <ul>
|
|
||||||
* <li> "kicad" is the logical library name.
|
|
||||||
* <li> "passives" is the category.
|
|
||||||
* <li> "passives/R" is the partname.
|
|
||||||
* <li> "rev6" is the revision number, which is optional. If missing then its
|
|
||||||
* delimiter should also not be present.
|
|
||||||
* </ul>
|
|
||||||
* <p>
|
|
||||||
* This class owns the <b>library table</b>, which is like fstab in concept and maps logical
|
|
||||||
* library name to library URI, type, and options. It has the following columns:
|
|
||||||
* <ul>
|
|
||||||
* <li> Logical Library Name
|
|
||||||
* <li> Library Type
|
|
||||||
* <li> Library URI. The full URI to the library source, form dependent on Type.
|
|
||||||
* <li> Options, used for access, such as password
|
|
||||||
* </ul>
|
|
||||||
* <p>
|
|
||||||
* For now, the Library Type can be one of:
|
|
||||||
* <ul>
|
|
||||||
* <li> "dir"
|
|
||||||
* <li> "schematic" i.e. a parts list from another schematic.
|
|
||||||
* <li> "subversion"
|
|
||||||
* <li> "bazaar"
|
|
||||||
* <li> "http"
|
|
||||||
* </ul>
|
|
||||||
* <p>
|
|
||||||
* For now, the Library URI types needed to support the various types can be one of those
|
|
||||||
* shown below, which are typical of each type:
|
|
||||||
* <ul>
|
|
||||||
* <li> "file://C:/mylibdir"
|
|
||||||
* <li> "file://home/user/kicadwork/jtagboard.sch"
|
|
||||||
* <li> "svn://kicad.org/partlib/trunk"
|
|
||||||
* <li> "http://kicad.org/partlib"
|
|
||||||
* </ul>
|
|
||||||
* <p>
|
|
||||||
* The applicable library table is built up from several additive rows (table fragments),
|
|
||||||
* and the final table is a merging of the table fragments. Two anticipated sources of
|
|
||||||
* the rows are a personal table, and a schematic resident table. The schematic
|
|
||||||
* resident table rows are considered a higher priority in the final dynamically
|
|
||||||
* assembled library table. A row in the schematic contribution to the library table
|
|
||||||
* will take precedence over the personal table if there is a collision on logical
|
|
||||||
* library name, otherwise the rows simply combine without issue to make up the
|
|
||||||
* applicable library table.
|
|
||||||
*/
|
|
||||||
class LPID // aka GUID
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Constructor LPID
|
|
||||||
* takes aLPID string and parses it. A typical LPID string uses a logical
|
|
||||||
* library name followed by a part name.
|
|
||||||
* e.g.: "kicad:passives/R/rev2", or
|
|
||||||
* e.g.: "mylib:R33"
|
|
||||||
*/
|
|
||||||
LPID( const STRING& aLPID ) throw( PARSE_ERROR );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetLogLib
|
|
||||||
* returns the logical library portion of a LPID. There is not Set accessor
|
|
||||||
* for this portion since it comes from the library table and is considered
|
|
||||||
* read only here.
|
|
||||||
*/
|
|
||||||
STRING GetLogLib() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetCategory
|
|
||||||
* returns the category of this part id, "passives" in the example at the
|
|
||||||
* top of the class description.
|
|
||||||
*/
|
|
||||||
STRING GetCategory() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function SetCategory
|
|
||||||
* overrides the category portion of the LPID to @a aCategory and is typically
|
|
||||||
* either the empty string or a single word like "passives".
|
|
||||||
*/
|
|
||||||
void SetCategory( const STRING& aCategory );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetRevision
|
|
||||||
* returns the revision portion of the LPID or StrEmpty if none.
|
|
||||||
*/
|
|
||||||
STRING GetRevision() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function SetRevision
|
|
||||||
* overrides the revision portion of the LPID to @a aRevision and must
|
|
||||||
* be in the form "rev<num>" where "<num>" is "1", "2", etc.
|
|
||||||
*/
|
|
||||||
void SetRevision( const STRING& aRevision );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetFullText
|
|
||||||
* returns the full text of the LPID.
|
|
||||||
*/
|
|
||||||
STRING GetFullText() const;
|
|
||||||
|
|
||||||
|
|
||||||
//-----<statics>-----------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetLogicalLibraries
|
|
||||||
* returns the logical library names, all of them that are in the
|
|
||||||
* library table.
|
|
||||||
* @param aSchematic provides access to the full library table inclusive
|
|
||||||
* of the schematic contribution, or may be NULL to exclude the schematic rows.
|
|
||||||
*/
|
|
||||||
static STRINGS GetLogicalLibraries( SCHEMATIC* aSchematic=NULL );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetLibraryURI
|
|
||||||
* returns the full library path from a logical library name.
|
|
||||||
* @param aLogicalLibraryName is the short name for the library of interest.
|
|
||||||
* @param aSchematic provides access to the full library table inclusive
|
|
||||||
* of the schematic contribution, or may be NULL to exclude the schematic rows.
|
|
||||||
*/
|
|
||||||
static STRING GetLibraryURI( const STRING& aLogicalLibraryName,
|
|
||||||
SCHEMATIC* aSchematic=NULL ) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetLibraryType
|
|
||||||
* returns the type of a logical library.
|
|
||||||
* @param aLogicalLibraryName is the short name for the library of interest.
|
|
||||||
* @param aSchematic provides access to the full library table inclusive
|
|
||||||
* of the schematic contribution, or may be NULL to exclude the schematic rows.
|
|
||||||
*/
|
|
||||||
static STRING GetLibraryType( const STRING& aLogicalLibraryName,
|
|
||||||
SCHEMATIC* aSchematic=NULL ) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetOptions
|
|
||||||
* returns the options string for \a aLogicalLibraryName.
|
|
||||||
* @param aLogicalLibraryName is the short name for the library of interest.
|
|
||||||
* @param aSchematic provides access to the full library table inclusive
|
|
||||||
* of the schematic contribution, or may be NULL to exclude the schematic rows.
|
|
||||||
*/
|
|
||||||
static STRING GetPassword( const STRING& aLogicalLibraryName,
|
|
||||||
SCHEMATIC* aSchematic=NULL ) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SVN_LIB_SOURCE
|
* Class SVN_LIB_SOURCE
|
||||||
* implements a LIB_SOURCE in a subversion repository.
|
* implements a LIB_SOURCE in a subversion repository.
|
||||||
|
|
|
@ -30,8 +30,10 @@ using namespace std;
|
||||||
using namespace SCH;
|
using namespace SCH;
|
||||||
|
|
||||||
|
|
||||||
LIB_TABLE::LIB_TABLE( LIB_TABLE* aFallBackTable )
|
LIB_TABLE::LIB_TABLE( LIB_TABLE* aFallBackTable ) :
|
||||||
|
fallBack( aFallBackTable )
|
||||||
{
|
{
|
||||||
|
/* not copying fall back, simply search it separately if "logicalName not found".
|
||||||
if( aFallBackTable )
|
if( aFallBackTable )
|
||||||
{
|
{
|
||||||
const ROWS& t = aFallBackTable->rows;
|
const ROWS& t = aFallBackTable->rows;
|
||||||
|
@ -39,12 +41,12 @@ LIB_TABLE::LIB_TABLE( LIB_TABLE* aFallBackTable )
|
||||||
for( ROWS_CITER it = t.begin(); it != t.end(); ++it )
|
for( ROWS_CITER it = t.begin(); it != t.end(); ++it )
|
||||||
{
|
{
|
||||||
// our rows are empty, expect no collisions here
|
// our rows are empty, expect no collisions here
|
||||||
auto_ptr<ROW> row( new ROW( *it ) );
|
auto_ptr<ROW> row( new ROW( *it->second ) );
|
||||||
|
|
||||||
row->owner = this;
|
row->owner = this;
|
||||||
rows.insert( row.release() );
|
insert( row );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,18 +128,89 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR )
|
||||||
in->NeedRIGHT();
|
in->NeedRIGHT();
|
||||||
in->NeedRIGHT(); // teriminate the (lib..)
|
in->NeedRIGHT(); // teriminate the (lib..)
|
||||||
|
|
||||||
rows.insert( row.release() );
|
// all logicalNames within this table fragment must be unique, so we do not
|
||||||
|
// replace. However a fallBack table can have a conflicting logicalName
|
||||||
|
// and ours will supercede that one since in findLib() we search this table
|
||||||
|
// before any fall back.
|
||||||
|
if( !InsertLib( row ) )
|
||||||
|
{
|
||||||
|
char buf[300];
|
||||||
|
|
||||||
|
snprintf( buf, sizeof(buf),
|
||||||
|
"'%s' is a duplicate logical lib name",
|
||||||
|
row->logicalName.c_str() );
|
||||||
|
throw IO_ERROR( buf );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 1
|
void LIB_TABLE::Format( OUTPUTFORMATTER* out, int nestLevel ) const
|
||||||
|
throw( IO_ERROR )
|
||||||
|
{
|
||||||
|
out->Print( nestLevel, "(lib_table\n" );
|
||||||
|
for( ROWS_CITER it = rows.begin(); it != rows.end(); ++it )
|
||||||
|
it->second->Format( out, nestLevel+1 );
|
||||||
|
out->Print( nestLevel, ")\n" );
|
||||||
|
}
|
||||||
|
|
||||||
int main( int argc, char** argv )
|
void LIB_TABLE::ROW::Format( OUTPUTFORMATTER* out, int nestLevel ) const
|
||||||
|
throw( IO_ERROR )
|
||||||
|
{
|
||||||
|
out->Print( nestLevel, "(lib (logical \"%s\")(type \"%s\")(full_uri \"%s\")(options \"%s\"))\n",
|
||||||
|
logicalName.c_str(), libType.c_str(), fullURI.c_str(), options.c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const LIB_TABLE::ROW* LIB_TABLE::FindLib( const STRING& aLogicalName )
|
||||||
|
{
|
||||||
|
// this function must be *super* fast, so therefore should not instantiate
|
||||||
|
// anything which would require using the heap. This function is the reason
|
||||||
|
// ptr_map<> was used instead of ptr_set<>, which would have required
|
||||||
|
// instantiating a ROW just to find a ROW.
|
||||||
|
|
||||||
|
ROWS_CITER it = rows.find( aLogicalName );
|
||||||
|
|
||||||
|
if( it != rows.end() )
|
||||||
|
{
|
||||||
|
// reference: http://myitcorner.com/blog/?p=361
|
||||||
|
return (const LIB_TABLE::ROW*) it->second; // found
|
||||||
|
}
|
||||||
|
|
||||||
|
// not found, search fall back table
|
||||||
|
if( fallBack )
|
||||||
|
return fallBack->FindLib( aLogicalName );
|
||||||
|
|
||||||
|
return 0; // not found
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LIB_TABLE::InsertLib( auto_ptr<ROW>& aRow, bool doReplace )
|
||||||
|
{
|
||||||
|
ROWS_ITER it = rows.find( aRow->logicalName );
|
||||||
|
|
||||||
|
if( doReplace || it == rows.end() )
|
||||||
|
{
|
||||||
|
// be careful here, key is needed because aRow can be
|
||||||
|
// release()ed before logicalName is captured.
|
||||||
|
const STRING& key = aRow->logicalName;
|
||||||
|
rows.insert( key, aRow );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 1 && defined(DEBUG)
|
||||||
|
|
||||||
|
// build this with a Debug CMAKE_BUILD_TYPE
|
||||||
|
|
||||||
|
void LIB_TABLE::Test()
|
||||||
{
|
{
|
||||||
// the null string is not really a legal DSN token since any double quotes
|
// the null string is not really a legal DSN token since any double quotes
|
||||||
// as assumed to be a single quote. To pass an empty string, we pass " "
|
// are assumed to be a single quote. To pass an empty string, we pass " "
|
||||||
// to (options " ")
|
// to (options " ")
|
||||||
SCH_LIB_TABLE_LEXER slr(
|
SCH_LIB_TABLE_LEXER slr(
|
||||||
"(lib_table \n"
|
"(lib_table \n"
|
||||||
|
@ -148,16 +221,14 @@ int main( int argc, char** argv )
|
||||||
wxT( "inline text" ) // source
|
wxT( "inline text" ) // source
|
||||||
);
|
);
|
||||||
|
|
||||||
LIB_TABLE lib_table;
|
|
||||||
|
|
||||||
// read the "( lib_table" pair of tokens
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// read the "( lib_table" pair of tokens
|
||||||
slr.NextTok();
|
slr.NextTok();
|
||||||
slr.NextTok();
|
slr.NextTok();
|
||||||
|
|
||||||
lib_table.Parse( &slr );
|
// parse the rest of input to slr
|
||||||
|
Parse( &slr );
|
||||||
}
|
}
|
||||||
|
|
||||||
catch( std::exception& ex )
|
catch( std::exception& ex )
|
||||||
|
@ -167,11 +238,36 @@ int main( int argc, char** argv )
|
||||||
|
|
||||||
catch( IO_ERROR ioe )
|
catch( IO_ERROR ioe )
|
||||||
{
|
{
|
||||||
printf( "caught\n" );
|
|
||||||
printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) );
|
printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
lib_table.Show();
|
STRING_FORMATTER sf;
|
||||||
|
|
||||||
|
Format( &sf, 0 );
|
||||||
|
|
||||||
|
printf( "test 'Parse() <-> Format()' round tripping:\n" );
|
||||||
|
printf( "%s", sf.GetString().c_str() );
|
||||||
|
|
||||||
|
printf( "\ntest a lookup of 'www':\n" );
|
||||||
|
sf.Clear();
|
||||||
|
|
||||||
|
const LIB_TABLE::ROW* www = FindLib( "www" );
|
||||||
|
if( www )
|
||||||
|
{
|
||||||
|
// found, print it just to prove it.
|
||||||
|
www->Format( &sf, 1 );
|
||||||
|
printf( "%s", sf.GetString().c_str() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf( "not found\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
LIB_TABLE lib_table;
|
||||||
|
|
||||||
|
lib_table.Test();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,13 +26,17 @@
|
||||||
#define SCH_LIB_TABLE_H_
|
#define SCH_LIB_TABLE_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/ptr_container/ptr_set.hpp>
|
#include <boost/ptr_container/ptr_map.hpp>
|
||||||
#include <sch_lib.h>
|
#include <sch_lib.h>
|
||||||
|
|
||||||
class SCH_LIB_TABLE_LEXER; // outside namespace SCH, since make_lexer() Functions.cmake can't do namespace
|
class SCH_LIB_TABLE_LEXER; // outside namespace SCH, since make_lexer() Functions.cmake can't do namespace
|
||||||
|
class OUTPUTFORMATTER;
|
||||||
|
|
||||||
namespace SCH {
|
namespace SCH {
|
||||||
|
|
||||||
|
class LPID;
|
||||||
|
class PART;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class LIB_TABLE
|
* Class LIB_TABLE
|
||||||
* holds LIB_TABLE::ROW records, and can be searched in a very high speed
|
* holds LIB_TABLE::ROW records, and can be searched in a very high speed
|
||||||
|
@ -54,10 +58,12 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/* was needed for ptr_set<> but not ptr_map<>
|
||||||
bool operator<( const ROW& other ) const
|
bool operator<( const ROW& other ) const
|
||||||
{
|
{
|
||||||
return logicalName < other.logicalName;
|
return logicalName < other.logicalName;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetLogicalName
|
* Function GetLogicalName
|
||||||
|
@ -101,13 +107,16 @@ public:
|
||||||
delete lib;
|
delete lib;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DEBUG)
|
/**
|
||||||
void Show() const
|
* Function Format
|
||||||
{
|
* serializes this object as utf8 text to an OUTPUTFORMATTER, and tries to
|
||||||
printf( "(lib (logical \"%s\")(type \"%s\")(full_uri \"%s\")(options \"%s\"))\n",
|
* make it look good using multiple lines and indentation.
|
||||||
logicalName.c_str(), libType.c_str(), fullURI.c_str(), options.c_str() );
|
* @param out is an OUTPUTFORMATTER
|
||||||
}
|
* @param nestLevel is the indentation level to base all lines of the output.
|
||||||
#endif
|
* Actual indentation will be 2 spaces for each nestLevel.
|
||||||
|
*/
|
||||||
|
void Format( OUTPUTFORMATTER* out, int nestLevel ) const
|
||||||
|
throw( IO_ERROR );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -195,23 +204,100 @@ public:
|
||||||
*/
|
*/
|
||||||
void Parse( SCH_LIB_TABLE_LEXER* aLexer ) throw( IO_ERROR );
|
void Parse( SCH_LIB_TABLE_LEXER* aLexer ) throw( IO_ERROR );
|
||||||
|
|
||||||
#if defined(DEBUG)
|
/**
|
||||||
void Show() const
|
* Function Format
|
||||||
{
|
* serializes this object as utf8 text to an OUTPUTFORMATTER, and tries to
|
||||||
printf("(lib_table\n" );
|
* make it look good using multiple lines and indentation.
|
||||||
for( ROWS_CITER it = rows.begin(); it != rows.end(); ++it )
|
* @param out is an OUTPUTFORMATTER
|
||||||
it->Show();
|
* @param nestLevel is the indentation level to base all lines of the output.
|
||||||
printf(")\n" );
|
* Actual indentation will be 2 spaces for each nestLevel.
|
||||||
}
|
*/
|
||||||
|
void Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetPart
|
||||||
|
* finds and loads a PART, and parses it. As long as the part is
|
||||||
|
* accessible in any LIB_SOURCE, opened or not opened, this function
|
||||||
|
* will find it and load it into its containing LIB, even if that means
|
||||||
|
* having to open a LIB in this table that was not previously opened.
|
||||||
|
*/
|
||||||
|
PART* GetPart( const LPID& aLogicalPartID ) throw( IO_ERROR );
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 // moved here from LPID
|
||||||
|
/**
|
||||||
|
* Function GetLogicalLibraries
|
||||||
|
* returns the logical library names, all of them that are in the
|
||||||
|
* library table.
|
||||||
|
*/
|
||||||
|
STRINGS GetLogicalLibraries();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetLibraryURI
|
||||||
|
* returns the full library path from a logical library name.
|
||||||
|
* @param aLogicalLibraryName is the short name for the library of interest.
|
||||||
|
* @param aSchematic provides access to the full library table inclusive
|
||||||
|
* of the schematic contribution, or may be NULL to exclude the schematic rows.
|
||||||
|
*/
|
||||||
|
STRING GetLibraryURI( const STRING& aLogicalLibraryName,
|
||||||
|
SCHEMATIC* aSchematic=NULL ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetLibraryType
|
||||||
|
* returns the type of a logical library.
|
||||||
|
* @param aLogicalLibraryName is the short name for the library of interest.
|
||||||
|
* @param aSchematic provides access to the full library table inclusive
|
||||||
|
* of the schematic contribution, or may be NULL to exclude the schematic rows.
|
||||||
|
*/
|
||||||
|
STRING GetLibraryType( const STRING& aLogicalLibraryName,
|
||||||
|
SCHEMATIC* aSchematic=NULL ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetOptions
|
||||||
|
* returns the options string for \a aLogicalLibraryName.
|
||||||
|
* @param aLogicalLibraryName is the short name for the library of interest.
|
||||||
|
* @param aSchematic provides access to the full library table inclusive
|
||||||
|
* of the schematic contribution, or may be NULL to exclude the schematic rows.
|
||||||
|
*/
|
||||||
|
STRING GetOptions( const STRING& aLogicalLibraryName,
|
||||||
|
SCHEMATIC* aSchematic=NULL ) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef boost::ptr_set<ROW> ROWS;
|
|
||||||
typedef ROWS::iterator ROWS_ITER;
|
#if defined(DEBUG)
|
||||||
typedef ROWS::const_iterator ROWS_CITER;
|
/// implement the tests in here so we can honor the priviledge levels of the
|
||||||
|
/// accessors, something difficult to do from int main(int, char**)
|
||||||
|
void Test();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected: // only a table editor can use these
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function InsertLib
|
||||||
|
* adds aRow if it does not already exist or if doReplace is true. If doReplace
|
||||||
|
* is not true and the key for aRow already exists, the function fails and returns false.
|
||||||
|
* @param aRow is the new row to insert, or to forcibly add if doReplace is true.
|
||||||
|
* @param doReplace if true, means insert regardless if aRow's key already exists. If false, then fail
|
||||||
|
* if the key already exists.
|
||||||
|
* @return bool - true if the operation succeeded.
|
||||||
|
*/
|
||||||
|
bool InsertLib( std::auto_ptr<ROW>& aRow, bool doReplace = false );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function FindLib
|
||||||
|
* returns a ROW* if aLogicalName is found in this table or in fallBack.
|
||||||
|
*/
|
||||||
|
const ROW* FindLib( const STRING& aLogicalName );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ROWS rows;
|
typedef boost::ptr_map<STRING, ROW> ROWS;
|
||||||
|
typedef ROWS::iterator ROWS_ITER;
|
||||||
|
typedef ROWS::const_iterator ROWS_CITER;
|
||||||
|
// typedef std::pair<ROWS_ITER, bool> ROW_PAIR;
|
||||||
|
|
||||||
|
ROWS rows;
|
||||||
|
LIB_TABLE* fallBack;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SCH
|
} // namespace SCH
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
|
* Copyright (C) 2010 Kicad Developers, see change_log.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sch_lpid.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace SCH;
|
||||||
|
|
||||||
|
|
||||||
|
LPID::LPID( const STRING& aLPID ) throw( PARSE_ERROR )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
|
* Copyright (C) 2010 Kicad Developers, see change_log.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SCH_LPID_H_
|
||||||
|
#define SCH_LPID_H_
|
||||||
|
|
||||||
|
//#include <wx/string.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class LPID
|
||||||
|
* (aka GUID) is a Logical Part ID and consists of various portions much like a URI.
|
||||||
|
* It relies heavily on a logical library name to hide where actual physical library
|
||||||
|
* sources reside. Its static functions serve as managers of the "library table" to
|
||||||
|
* map logical library names to actual library sources.
|
||||||
|
* <p>
|
||||||
|
* Example LPID string:
|
||||||
|
* "kicad:passives/R/rev6".
|
||||||
|
* <p>
|
||||||
|
* <ul>
|
||||||
|
* <li> "kicad" is the logical library name.
|
||||||
|
* <li> "passives" is the category.
|
||||||
|
* <li> "passives/R" is the partname.
|
||||||
|
* <li> "rev6" is the revision number, which is optional. If missing then its
|
||||||
|
* delimiter should also not be present.
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* This class owns the <b>library table</b>, which is like fstab in concept and maps logical
|
||||||
|
* library name to library URI, type, and options. It has the following columns:
|
||||||
|
* <ul>
|
||||||
|
* <li> Logical Library Name
|
||||||
|
* <li> Library Type
|
||||||
|
* <li> Library URI. The full URI to the library source, form dependent on Type.
|
||||||
|
* <li> Options, used for access, such as password
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* For now, the Library Type can be one of:
|
||||||
|
* <ul>
|
||||||
|
* <li> "dir"
|
||||||
|
* <li> "schematic" i.e. a parts list from another schematic.
|
||||||
|
* <li> "subversion"
|
||||||
|
* <li> "bazaar"
|
||||||
|
* <li> "http"
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* For now, the Library URI types needed to support the various types can be one of those
|
||||||
|
* shown below, which are typical of each type:
|
||||||
|
* <ul>
|
||||||
|
* <li> "file://C:/mylibdir"
|
||||||
|
* <li> "file://home/user/kicadwork/jtagboard.sch"
|
||||||
|
* <li> "svn://kicad.org/partlib/trunk"
|
||||||
|
* <li> "http://kicad.org/partlib"
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* The applicable library table is built up from several additive rows (table fragments),
|
||||||
|
* and the final table is a merging of the table fragments. Two anticipated sources of
|
||||||
|
* the rows are a personal table, and a schematic resident table. The schematic
|
||||||
|
* resident table rows are considered a higher priority in the final dynamically
|
||||||
|
* assembled library table. A row in the schematic contribution to the library table
|
||||||
|
* will take precedence over the personal table if there is a collision on logical
|
||||||
|
* library name, otherwise the rows simply combine without issue to make up the
|
||||||
|
* applicable library table.
|
||||||
|
*/
|
||||||
|
class LPID // aka GUID
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor LPID
|
||||||
|
* takes aLPID string and parses it. A typical LPID string uses a logical
|
||||||
|
* library name followed by a part name.
|
||||||
|
* e.g.: "kicad:passives/R/rev2", or
|
||||||
|
* e.g.: "mylib:R33"
|
||||||
|
*/
|
||||||
|
LPID( const STRING& aLPID ) throw( PARSE_ERROR );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetLogLib
|
||||||
|
* returns the logical library portion of a LPID. There is not Set accessor
|
||||||
|
* for this portion since it comes from the library table and is considered
|
||||||
|
* read only here.
|
||||||
|
*/
|
||||||
|
STRING GetLogLib() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetCategory
|
||||||
|
* returns the category of this part id, "passives" in the example at the
|
||||||
|
* top of the class description.
|
||||||
|
*/
|
||||||
|
STRING GetCategory() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetCategory
|
||||||
|
* overrides the category portion of the LPID to @a aCategory and is typically
|
||||||
|
* either the empty string or a single word like "passives".
|
||||||
|
*/
|
||||||
|
void SetCategory( const STRING& aCategory );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetRevision
|
||||||
|
* returns the revision portion of the LPID or StrEmpty if none.
|
||||||
|
*/
|
||||||
|
STRING GetRevision() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetRevision
|
||||||
|
* overrides the revision portion of the LPID to @a aRevision and must
|
||||||
|
* be in the form "rev<num>" where "<num>" is "1", "2", etc.
|
||||||
|
*/
|
||||||
|
void SetRevision( const STRING& aRevision );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetFullText
|
||||||
|
* returns the full text of the LPID.
|
||||||
|
*/
|
||||||
|
STRING GetFullText() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SCH_LPID_H_
|
|
@ -174,7 +174,7 @@ bool WinEDA_PcbFrame::ReadPcbNetlist( const wxString& aNetlistFullFilename,
|
||||||
if( !netfile )
|
if( !netfile )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
FILE_LINE_READER netlistReader( netfile, aNetlistFullFilename, BUFFER_CHAR_SIZE );
|
FILE_LINE_READER netlistReader( netfile, aNetlistFullFilename );
|
||||||
char* Line = netlistReader;
|
char* Line = netlistReader;
|
||||||
|
|
||||||
SetLastNetListRead( aNetlistFullFilename );
|
SetLastNetListRead( aNetlistFullFilename );
|
||||||
|
@ -798,7 +798,7 @@ int BuildFootprintsListFromNetlistFile( const wxString& aNetlistFullFilename,
|
||||||
if( !netfile )
|
if( !netfile )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
FILE_LINE_READER netlistReader( netfile, aNetlistFullFilename, BUFFER_CHAR_SIZE );
|
FILE_LINE_READER netlistReader( netfile, aNetlistFullFilename );
|
||||||
char* Line = netlistReader;
|
char* Line = netlistReader;
|
||||||
|
|
||||||
State = 0; Comment = 0;
|
State = 0; Comment = 0;
|
||||||
|
@ -901,7 +901,7 @@ int ReadListeModules( const wxString& CmpFullFileName, const wxString* RefCmp,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE_LINE_READER netlistReader( FichCmp, CmpFullFileName, BUFFER_CHAR_SIZE );
|
FILE_LINE_READER netlistReader( FichCmp, CmpFullFileName );
|
||||||
char* Line = netlistReader;
|
char* Line = netlistReader;
|
||||||
|
|
||||||
while( netlistReader.ReadLine() )
|
while( netlistReader.ReadLine() )
|
||||||
|
|
Loading…
Reference in New Issue