see CHANGELOG.txt
This commit is contained in:
parent
7bcb4ff34e
commit
d2cc77ac71
|
@ -5,9 +5,6 @@ eeschema/cmp_library_lexer.h
|
||||||
eeschema/cmp_library_keywords.*
|
eeschema/cmp_library_keywords.*
|
||||||
eeschema/template_fieldnames_keywords.*
|
eeschema/template_fieldnames_keywords.*
|
||||||
eeschema/template_fieldnames_lexer.h
|
eeschema/template_fieldnames_lexer.h
|
||||||
new/html
|
|
||||||
new/sch_lib_table_keywords.cpp
|
|
||||||
new/sch_lib_table_lexer.h
|
|
||||||
pcbnew/dialogs/dialog_freeroute_exchange_help_html.h
|
pcbnew/dialogs/dialog_freeroute_exchange_help_html.h
|
||||||
Makefile
|
Makefile
|
||||||
CMakeFiles
|
CMakeFiles
|
||||||
|
@ -20,3 +17,8 @@ install_manifest.txt
|
||||||
Documentation/doxygen
|
Documentation/doxygen
|
||||||
*.cmake
|
*.cmake
|
||||||
*.bak
|
*.bak
|
||||||
|
new/html
|
||||||
|
new/sch_lib_table_keywords.cpp
|
||||||
|
new/sch_lib_table_lexer.h
|
||||||
|
new/sweet_keywords.cpp
|
||||||
|
new/sweet_lexer.h
|
||||||
|
|
|
@ -4,6 +4,19 @@ KiCad ChangeLog 2010
|
||||||
Please add newer entries at the top, list the date and your name with
|
Please add newer entries at the top, list the date and your name with
|
||||||
email address.
|
email address.
|
||||||
|
|
||||||
|
2010-Dec-28 UPDATE Dick Hollenbeck <dick@softplc.com>
|
||||||
|
================================================================================
|
||||||
|
++richio:
|
||||||
|
* Deleted kicad_exceptions, because it required the big #include <wx/wx.h> and
|
||||||
|
that was slowing down compiling. Moved that stuff back into richio.h where
|
||||||
|
it came from.
|
||||||
|
* Enhanced IO_ERROR to format an errorText.
|
||||||
|
* Added THROW_IO_ERROR() and THROW_PARSE_ERROR() macros to capture the
|
||||||
|
the call site of the thrower. If you have problems compiling, it is probably
|
||||||
|
due to the definition of __LOC__ in richio.h. Some compilers may not support
|
||||||
|
__func__ in C++ yet. Find a macro that identifies your compiler, and we can
|
||||||
|
work out something in the #define of __LOC__.
|
||||||
|
|
||||||
2010-Dec-28 UPDATE Dick Hollenbeck <dick@softplc.com>
|
2010-Dec-28 UPDATE Dick Hollenbeck <dick@softplc.com>
|
||||||
================================================================================
|
================================================================================
|
||||||
++new:
|
++new:
|
||||||
|
|
|
@ -251,12 +251,14 @@ bool DSNLEXER::IsSymbol( int aTok )
|
||||||
|
|
||||||
void DSNLEXER::ThrowIOError( wxString aText, int charOffset ) throw( IO_ERROR )
|
void DSNLEXER::ThrowIOError( wxString aText, int charOffset ) throw( IO_ERROR )
|
||||||
{
|
{
|
||||||
|
// @todo convert this to THROW_PARSE_ERROR()
|
||||||
|
|
||||||
// append to aText, do not overwrite
|
// append to aText, do not overwrite
|
||||||
aText << wxT(" ") << _("in") << wxT(" \"") << CurSource()
|
aText << wxT(" ") << _("in") << wxT(" \"") << CurSource()
|
||||||
<< wxT("\" ") << _("on line") << wxT(" ") << reader->LineNumber()
|
<< wxT("\" ") << _("on line") << wxT(" ") << reader->LineNumber()
|
||||||
<< wxT(" ") << _("at offset") << wxT(" ") << charOffset;
|
<< wxT(" ") << _("at offset") << wxT(" ") << charOffset;
|
||||||
|
|
||||||
throw IO_ERROR( aText );
|
THROW_IO_ERROR( aText );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR )
|
||||||
length += strlen( line + length );
|
length += strlen( line + length );
|
||||||
|
|
||||||
if( length == maxLineLength )
|
if( length == maxLineLength )
|
||||||
throw IO_ERROR( _("Line length exceeded") );
|
THROW_IO_ERROR( _("Line length exceeded") );
|
||||||
|
|
||||||
// a normal line breaks here, once through while loop
|
// a normal line breaks here, once through while loop
|
||||||
if( length+1 < capacity || line[length-1] == '\n' )
|
if( length+1 < capacity || line[length-1] == '\n' )
|
||||||
|
@ -164,7 +164,7 @@ unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR )
|
||||||
if( length )
|
if( length )
|
||||||
{
|
{
|
||||||
if( length >= maxLineLength )
|
if( length >= maxLineLength )
|
||||||
throw IO_ERROR( _("Line length exceeded") );
|
THROW_IO_ERROR( _("Line length exceeded") );
|
||||||
|
|
||||||
if( length+1 > capacity ) // +1 for terminating nul
|
if( length+1 > capacity ) // +1 for terminating nul
|
||||||
expandCapacity( length+1 );
|
expandCapacity( length+1 );
|
||||||
|
@ -305,7 +305,7 @@ std::string OUTPUTFORMATTER::Quoted( const std::string& aWrapee ) throw( IO_ERRO
|
||||||
// a decision was made to make all S-expression strings be on a single
|
// a decision was made to make all S-expression strings be on a single
|
||||||
// line. You can embed \n (human readable) in the text but not
|
// line. You can embed \n (human readable) in the text but not
|
||||||
// '\n' which is 0x0a.
|
// '\n' which is 0x0a.
|
||||||
throw IO_ERROR( _( "S-expression string has newline" ) );
|
THROW_IO_ERROR( _( "S-expression string has newline" ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,7 +363,7 @@ void STREAM_OUTPUTFORMATTER::write( const char* aOutBuf, int aCount ) throw( IO_
|
||||||
|
|
||||||
if( !os.IsOk() )
|
if( !os.IsOk() )
|
||||||
{
|
{
|
||||||
throw IO_ERROR( _( "OUTPUTSTREAM_OUTPUTFORMATTER write error" ) );
|
THROW_IO_ERROR( _( "OUTPUTSTREAM_OUTPUTFORMATTER write error" ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,25 +17,6 @@ class LIB_PIN;
|
||||||
class LIB_COMPONENT;
|
class LIB_COMPONENT;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holder of an error message and may be thrown from functions.
|
|
||||||
*/
|
|
||||||
struct Error
|
|
||||||
{
|
|
||||||
wxString errorText;
|
|
||||||
|
|
||||||
Error( const wxChar* aMsg ) :
|
|
||||||
errorText( aMsg )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Error( const wxString& aMsg ) :
|
|
||||||
errorText( aMsg )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A container for several SCH_FIELD items
|
/// A container for several SCH_FIELD items
|
||||||
typedef std::vector<SCH_FIELD> SCH_FIELDS;
|
typedef std::vector<SCH_FIELD> SCH_FIELDS;
|
||||||
|
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
/*
|
|
||||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 SoftPLC Corporation, <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 KICAD_EXCEPTIONS_H_
|
|
||||||
#define KICAD_EXCEPTIONS_H_
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ingroup exception_types
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <wx/string.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Struct IO_ERROR
|
|
||||||
* is a class used to hold an error message and may be used to throw exceptions
|
|
||||||
* containing meaningful error messages.
|
|
||||||
* @author Dick Hollenbeck
|
|
||||||
*/
|
|
||||||
struct IO_ERROR
|
|
||||||
{
|
|
||||||
wxString errorText;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor ( const wxChar* )
|
|
||||||
* handles the case where _() is passed as aMsg.
|
|
||||||
*/
|
|
||||||
IO_ERROR( const wxChar* aMsg ) :
|
|
||||||
errorText( aMsg )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
IO_ERROR( const wxString& aMsg ) :
|
|
||||||
errorText( aMsg )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
IO_ERROR( const std::string& aMsg ) :
|
|
||||||
errorText( wxConvertMB2WX( aMsg.c_str() ) )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class PARSE_ERROR
|
|
||||||
* contains a filename or source description, a line number, a character offset,
|
|
||||||
* and an error message.
|
|
||||||
* @author Dick Hollenbeck
|
|
||||||
*/
|
|
||||||
struct PARSE_ERROR : public IO_ERROR
|
|
||||||
{
|
|
||||||
wxString source; ///< filename typically, or other source
|
|
||||||
int lineNumber;
|
|
||||||
int byteIndex; ///< char offset, starting from 1, into the problem line.
|
|
||||||
|
|
||||||
PARSE_ERROR( const wxString& aMsg, const wxString& aSource,
|
|
||||||
int aLineNumber, int aByteIndex ) :
|
|
||||||
IO_ERROR( aMsg ),
|
|
||||||
source( aSource ),
|
|
||||||
lineNumber( aLineNumber )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @} exception_types */
|
|
||||||
|
|
||||||
|
|
||||||
#endif // KICAD_EXCEPTIONS_H_
|
|
129
include/richio.h
129
include/richio.h
|
@ -38,7 +38,134 @@
|
||||||
// but the errorText needs to be wide char so wxString rules.
|
// but the errorText needs to be wide char so wxString rules.
|
||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <kicad_exceptions.h>
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup exception_types
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define IO_FORMAT _( "IO_ERROR: '%s'\n from %s : %s" )
|
||||||
|
#define PARSE_FORMAT _( "PARSE_ERROR: '%s' in input/source '%s', line %d, offset %d\n from %s : %s" )
|
||||||
|
|
||||||
|
// references:
|
||||||
|
// http://stackoverflow.com/questions/2670816/how-can-i-use-the-compile-time-constant-line-in-a-string
|
||||||
|
#define STRINGIFY(x) #x
|
||||||
|
#define TOSTRING(x) STRINGIFY(x)
|
||||||
|
|
||||||
|
// use one of the following __LOC__ defs, depending on whether your
|
||||||
|
// compiler supports __func__ or not, and how it handles __LINE__
|
||||||
|
#define __LOC__ ((std::string(__func__) + " : ") + TOSTRING(__LINE__)).c_str()
|
||||||
|
//#define __LOC__ TOSTRING(__LINE__)
|
||||||
|
|
||||||
|
/// macro which captures the "call site" values of __FILE_ & __LOC__
|
||||||
|
#define THROW_IO_ERROR( msg ) throw IO_ERROR( __FILE__, __LOC__, msg )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct IO_ERROR
|
||||||
|
* is a class used to hold an error message and may be used to throw exceptions
|
||||||
|
* containing meaningful error messages.
|
||||||
|
* @author Dick Hollenbeck
|
||||||
|
*/
|
||||||
|
struct IO_ERROR // : std::exception
|
||||||
|
{
|
||||||
|
wxString errorText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param aThrowersFile is the __FILE__ preprocessor macro but generated
|
||||||
|
* at the source file of thrower.
|
||||||
|
*
|
||||||
|
* @param aThrowersLoc can be either a function name, such as __func__
|
||||||
|
* or a stringified __LINE__ preprocessor macro but generated
|
||||||
|
* at the source function of the thrower, or concatonation. Use macro
|
||||||
|
* THROW_IO_ERROR() to wrap a call to this constructor at the call site.
|
||||||
|
*
|
||||||
|
* @param aMsg is error text that will be streamed through wxString.Printf()
|
||||||
|
* using the format string IO_FORMAT above.
|
||||||
|
*/
|
||||||
|
IO_ERROR( const char* aThrowersFile,
|
||||||
|
const char* aThrowersLoc,
|
||||||
|
const wxString& aMsg )
|
||||||
|
{
|
||||||
|
init( aThrowersFile, aThrowersLoc, aMsg );
|
||||||
|
}
|
||||||
|
|
||||||
|
IO_ERROR( const char* aThrowersFile,
|
||||||
|
const char* aThrowersLoc,
|
||||||
|
const std::string& aMsg )
|
||||||
|
{
|
||||||
|
init( aThrowersFile, aThrowersLoc, wxString::FromUTF8( aMsg.c_str() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* handles the case where _() is passed as aMsg.
|
||||||
|
*/
|
||||||
|
IO_ERROR( const char* aThrowersFile,
|
||||||
|
const char* aThrowersLoc,
|
||||||
|
const wxChar* aMsg )
|
||||||
|
{
|
||||||
|
init( aThrowersFile, aThrowersLoc, wxString( aMsg ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void init( const char* aThrowersFile, const char* aThrowersLoc, const wxString& aMsg )
|
||||||
|
{
|
||||||
|
errorText.Printf( IO_FORMAT, aMsg.GetData(),
|
||||||
|
wxString::FromUTF8( aThrowersFile ).GetData(),
|
||||||
|
wxString::FromUTF8( aThrowersLoc ).GetData() );
|
||||||
|
}
|
||||||
|
|
||||||
|
IO_ERROR() {}
|
||||||
|
|
||||||
|
~IO_ERROR() throw ( /*none*/ ){}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define THROW_PARSE_ERROR( msg, input, line, offset ) throw PARSE_ERROR( __FILE__, __LOC__, msg, input, line, offset )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class PARSE_ERROR
|
||||||
|
* contains a filename or source description, a line number, a character offset,
|
||||||
|
* and an error message.
|
||||||
|
* @author Dick Hollenbeck
|
||||||
|
*/
|
||||||
|
struct PARSE_ERROR : public IO_ERROR
|
||||||
|
{
|
||||||
|
// wxString errorText is still public from IO_ERROR
|
||||||
|
|
||||||
|
int lineNumber; ///< at which line number, 1 based index.
|
||||||
|
int byteIndex; ///< at which character position within the line, 1 based index
|
||||||
|
|
||||||
|
PARSE_ERROR( const char* aThrowersFile, const char* aThrowersLoc,
|
||||||
|
const wxString& aMsg, const wxString& aSource,
|
||||||
|
int aLineNumber, int aByteIndex ) :
|
||||||
|
IO_ERROR()
|
||||||
|
{
|
||||||
|
init( aThrowersFile, aThrowersLoc, aMsg, aSource, aLineNumber, aByteIndex );
|
||||||
|
}
|
||||||
|
|
||||||
|
void init( const char* aThrowersFile, const char* aThrowersLoc,
|
||||||
|
const wxString& aMsg, const wxString& aSource,
|
||||||
|
int aLineNumber, int aByteIndex )
|
||||||
|
{
|
||||||
|
// save line and offset in binary for Sweet text editor, which will catch exceptions
|
||||||
|
lineNumber = aLineNumber;
|
||||||
|
byteIndex = aByteIndex;
|
||||||
|
|
||||||
|
// #define PARSE_FORMAT _( "PARSE_ERROR: %s in source %s, line %d, offset %d\nfrom cpp:%s func:%s" )
|
||||||
|
|
||||||
|
errorText.Printf( PARSE_FORMAT, aMsg.GetData(), aSource.GetData(),
|
||||||
|
aLineNumber, aByteIndex,
|
||||||
|
wxString::FromUTF8( aThrowersFile ).GetData(),
|
||||||
|
wxString::FromUTF8( aThrowersLoc ).GetData() );
|
||||||
|
}
|
||||||
|
|
||||||
|
~PARSE_ERROR() throw ( /*none*/ ){}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @} exception_types */
|
||||||
|
|
||||||
|
|
||||||
#define LINE_READER_LINE_DEFAULT_MAX 100000
|
#define LINE_READER_LINE_DEFAULT_MAX 100000
|
||||||
|
|
|
@ -86,6 +86,8 @@ add_executable( test_sch_lib_table
|
||||||
sch_lib.cpp
|
sch_lib.cpp
|
||||||
sch_lpid.cpp
|
sch_lpid.cpp
|
||||||
sch_dir_lib_source.cpp
|
sch_dir_lib_source.cpp
|
||||||
|
sch_part.cpp
|
||||||
|
sweet_keywords.cpp
|
||||||
${PROJECT_SOURCE_DIR}/common/richio.cpp
|
${PROJECT_SOURCE_DIR}/common/richio.cpp
|
||||||
${PROJECT_SOURCE_DIR}/common/dsnlexer.cpp
|
${PROJECT_SOURCE_DIR}/common/dsnlexer.cpp
|
||||||
)
|
)
|
||||||
|
@ -98,3 +100,10 @@ make_lexer(
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table_keywords.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table_keywords.cpp
|
||||||
ELT_T
|
ELT_T
|
||||||
)
|
)
|
||||||
|
|
||||||
|
make_lexer(
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sweet.keywords
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sweet_lexer.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sweet_keywords.cpp
|
||||||
|
PART_T
|
||||||
|
)
|
||||||
|
|
|
@ -41,16 +41,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <sch_dir_lib_source.h>
|
|
||||||
using namespace SCH;
|
|
||||||
|
|
||||||
#include <kicad_exceptions.h>
|
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -61,11 +55,8 @@ using namespace SCH;
|
||||||
#include <vector>
|
#include <vector>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
/// This file extension is an implementation detail specific to this LIB_SOURCE
|
#include <sch_dir_lib_source.h>
|
||||||
/// implementation, and to a corresponding LIB_SINK.
|
using namespace SCH;
|
||||||
/// Core EESCHEMA should never have to see this.
|
|
||||||
#define SWEET_EXT ".part"
|
|
||||||
#define SWEET_EXTZ (sizeof(SWEET_EXT)-1)
|
|
||||||
|
|
||||||
|
|
||||||
/* __func__ is C99 prescribed, but just in case:
|
/* __func__ is C99 prescribed, but just in case:
|
||||||
|
@ -157,7 +148,7 @@ static inline bool isDigit( char c )
|
||||||
* segment, i.e. the string segment of interest is [start,tail)
|
* segment, i.e. the string segment of interest is [start,tail)
|
||||||
* @param separator is the separating byte, expected: '.' or '/', depending on context.
|
* @param separator is the separating byte, expected: '.' or '/', depending on context.
|
||||||
*/
|
*/
|
||||||
static const char* endsWithRev( const char* start, const char* tail, char separator )
|
static const char* endsWithRev( const char* start, const char* tail, char separator = '/' )
|
||||||
{
|
{
|
||||||
bool sawDigit = false;
|
bool sawDigit = false;
|
||||||
|
|
||||||
|
@ -181,7 +172,7 @@ static const char* endsWithRev( const char* start, const char* tail, char separa
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const char* endsWithRev( const STRING& aPartName, char separator )
|
static inline const char* endsWithRev( const STRING& aPartName, char separator = '/' )
|
||||||
{
|
{
|
||||||
return endsWithRev( aPartName.c_str(), aPartName.c_str()+aPartName.size(), separator );
|
return endsWithRev( aPartName.c_str(), aPartName.c_str()+aPartName.size(), separator );
|
||||||
}
|
}
|
||||||
|
@ -194,8 +185,8 @@ bool BY_REV::operator() ( const STRING& s1, const STRING& s2 ) const
|
||||||
{
|
{
|
||||||
// avoid instantiating new STRINGs, and thank goodness that c_str() is const.
|
// avoid instantiating new STRINGs, and thank goodness that c_str() is const.
|
||||||
|
|
||||||
const char* rev1 = endsWithRev( s1, '/' );
|
const char* rev1 = endsWithRev( s1 );
|
||||||
const char* rev2 = endsWithRev( s2, '/' );
|
const char* rev2 = endsWithRev( s2 );
|
||||||
|
|
||||||
int rootLen1 = rev1 ? rev1 - s1.c_str() : s1.size();
|
int rootLen1 = rev1 ? rev1 - s1.c_str() : s1.size();
|
||||||
int rootLen2 = rev2 ? rev2 - s2.c_str() : s2.size();
|
int rootLen2 = rev2 ? rev2 - s2.c_str() : s2.size();
|
||||||
|
@ -290,7 +281,7 @@ STRING DIR_LIB_SOURCE::makeFileName( const STRING& aPartName )
|
||||||
|
|
||||||
STRING fileName = sourceURI + "/";
|
STRING fileName = sourceURI + "/";
|
||||||
|
|
||||||
const char* rev = endsWithRev( aPartName, '/' );
|
const char* rev = endsWithRev( aPartName );
|
||||||
|
|
||||||
if( rev )
|
if( rev )
|
||||||
{
|
{
|
||||||
|
@ -318,7 +309,7 @@ void DIR_LIB_SOURCE::readString( STRING* aResult, const STRING& aFileName ) thro
|
||||||
{
|
{
|
||||||
STRING msg = strerror( errno );
|
STRING msg = strerror( errno );
|
||||||
msg += "; cannot open(O_RDONLY) file " + aFileName;
|
msg += "; cannot open(O_RDONLY) file " + aFileName;
|
||||||
throw( IO_ERROR( msg ) );
|
THROW_IO_ERROR( msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
struct stat fs;
|
struct stat fs;
|
||||||
|
@ -330,9 +321,14 @@ void DIR_LIB_SOURCE::readString( STRING* aResult, const STRING& aFileName ) thro
|
||||||
{
|
{
|
||||||
STRING msg = aFileName;
|
STRING msg = aFileName;
|
||||||
msg += " seems too big. ( > 1 mbyte )";
|
msg += " seems too big. ( > 1 mbyte )";
|
||||||
throw IO_ERROR( msg );
|
THROW_IO_ERROR( msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// I read somewhere on the Internet that std::string chars are not guaranteed
|
||||||
|
// (over time) to be contiguous in future implementations of C++, so this
|
||||||
|
// strategy is here for that eventuality. We buffer through readBuffer here.
|
||||||
|
|
||||||
// reuse same readBuffer, which is not thread safe, but the API
|
// reuse same readBuffer, which is not thread safe, but the API
|
||||||
// is not advertising thread safe (yet, if ever).
|
// is not advertising thread safe (yet, if ever).
|
||||||
if( (int) fs.st_size > (int) readBuffer.size() )
|
if( (int) fs.st_size > (int) readBuffer.size() )
|
||||||
|
@ -343,13 +339,27 @@ void DIR_LIB_SOURCE::readString( STRING* aResult, const STRING& aFileName ) thro
|
||||||
{
|
{
|
||||||
STRING msg = strerror( errno );
|
STRING msg = strerror( errno );
|
||||||
msg += "; cannot read file " + aFileName;
|
msg += "; cannot read file " + aFileName;
|
||||||
throw( IO_ERROR( msg ) );
|
THROW_IO_ERROR( msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::string chars are not guaranteed to be contiguous in
|
|
||||||
// future implementations of C++, so this is why we did not read into
|
|
||||||
// aResult directly.
|
|
||||||
aResult->assign( &readBuffer[0], count );
|
aResult->assign( &readBuffer[0], count );
|
||||||
|
#else
|
||||||
|
|
||||||
|
// read into the string directly
|
||||||
|
aResult->resize( fs.st_size );
|
||||||
|
|
||||||
|
int count = read( fw, &(*aResult)[0], fs.st_size );
|
||||||
|
if( count != (int) fs.st_size )
|
||||||
|
{
|
||||||
|
STRING msg = strerror( errno );
|
||||||
|
msg += "; cannot read file " + aFileName;
|
||||||
|
THROW_IO_ERROR( msg );
|
||||||
|
}
|
||||||
|
|
||||||
|
// test trailing nul is there, which should have been put there with resize() above
|
||||||
|
// printf( "'%s'\n", aResult->c_str() ); // checked OK.
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -371,7 +381,7 @@ DIR_LIB_SOURCE::DIR_LIB_SOURCE( const STRING& aDirectoryPath,
|
||||||
|
|
||||||
if( sourceURI.size() == 0 )
|
if( sourceURI.size() == 0 )
|
||||||
{
|
{
|
||||||
throw( IO_ERROR( STRING("aDirectoryPath cannot be empty") ) );
|
THROW_IO_ERROR( STRING("aDirectoryPath cannot be empty") );
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove any trailing separator, so we can add it back later without ambiguity
|
// remove any trailing separator, so we can add it back later without ambiguity
|
||||||
|
@ -406,7 +416,7 @@ void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& a
|
||||||
|
|
||||||
while( it != limit )
|
while( it != limit )
|
||||||
{
|
{
|
||||||
const char* rev = endsWithRev( *it, '/' );
|
const char* rev = endsWithRev( *it );
|
||||||
|
|
||||||
// all cached partnames have a rev string in useVersioning mode
|
// all cached partnames have a rev string in useVersioning mode
|
||||||
assert( rev );
|
assert( rev );
|
||||||
|
@ -434,7 +444,13 @@ void DIR_LIB_SOURCE::ReadPart( STRING* aResult, const STRING& aPartName, const S
|
||||||
throw( IO_ERROR )
|
throw( IO_ERROR )
|
||||||
{
|
{
|
||||||
STRING partName = aPartName; // appended with aRev too if not empty
|
STRING partName = aPartName; // appended with aRev too if not empty
|
||||||
const char* rev = endsWithRev( partName, '/' );
|
const char* rev = endsWithRev( partName );
|
||||||
|
|
||||||
|
if( !useVersioning && (aRev.size() || rev) )
|
||||||
|
{
|
||||||
|
STRING msg = "this type 'dir' LIB_SOURCE not using 'useVersioning' option, cannot ask for a revision";
|
||||||
|
THROW_IO_ERROR( msg );
|
||||||
|
}
|
||||||
|
|
||||||
if( aRev.size() )
|
if( aRev.size() )
|
||||||
{
|
{
|
||||||
|
@ -443,7 +459,7 @@ void DIR_LIB_SOURCE::ReadPart( STRING* aResult, const STRING& aPartName, const S
|
||||||
|
|
||||||
partName += "/" + aRev;
|
partName += "/" + aRev;
|
||||||
|
|
||||||
rev = endsWithRev( partName, '/' );
|
rev = endsWithRev( partName );
|
||||||
}
|
}
|
||||||
|
|
||||||
// partName is the exact part name we need here, or if rev is NULL,
|
// partName is the exact part name we need here, or if rev is NULL,
|
||||||
|
@ -456,7 +472,7 @@ void DIR_LIB_SOURCE::ReadPart( STRING* aResult, const STRING& aPartName, const S
|
||||||
if( it == partnames.end() ) // part not found
|
if( it == partnames.end() ) // part not found
|
||||||
{
|
{
|
||||||
partName += " not found.";
|
partName += " not found.";
|
||||||
throw IO_ERROR( partName );
|
THROW_IO_ERROR( partName );
|
||||||
}
|
}
|
||||||
|
|
||||||
readString( aResult, makeFileName( partName ) );
|
readString( aResult, makeFileName( partName ) );
|
||||||
|
@ -474,8 +490,9 @@ void DIR_LIB_SOURCE::ReadPart( STRING* aResult, const STRING& aPartName, const S
|
||||||
// some unrelated name that is larger.
|
// some unrelated name that is larger.
|
||||||
if( it == partnames.end() || it->compare( 0, search.size(), search ) != 0 )
|
if( it == partnames.end() || it->compare( 0, search.size(), search ) != 0 )
|
||||||
{
|
{
|
||||||
partName += " rev not found.";
|
partName.insert( partName.begin(), '\'' );
|
||||||
throw IO_ERROR( partName );
|
partName += "' is not present without a revision.";
|
||||||
|
THROW_IO_ERROR( partName );
|
||||||
}
|
}
|
||||||
|
|
||||||
readString( aResult, makeFileName( *it ) );
|
readString( aResult, makeFileName( *it ) );
|
||||||
|
@ -540,7 +557,7 @@ void DIR_LIB_SOURCE::cacheOneDir( const STRING& aCategory ) throw( IO_ERROR )
|
||||||
{
|
{
|
||||||
STRING msg = strerror( errno );
|
STRING msg = strerror( errno );
|
||||||
msg += "; scanning directory " + curDir;
|
msg += "; scanning directory " + curDir;
|
||||||
throw( IO_ERROR( msg ) );
|
THROW_IO_ERROR( msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
struct stat fs;
|
struct stat fs;
|
||||||
|
@ -566,7 +583,7 @@ void DIR_LIB_SOURCE::cacheOneDir( const STRING& aCategory ) throw( IO_ERROR )
|
||||||
{
|
{
|
||||||
STRING msg = partName;
|
STRING msg = partName;
|
||||||
msg += " has already been encountered";
|
msg += " has already been encountered";
|
||||||
throw IO_ERROR( msg );
|
THROW_IO_ERROR( msg );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,9 +666,9 @@ void DIR_LIB_SOURCE::Test( int argc, char** argv )
|
||||||
printf( "std::exception\n" );
|
printf( "std::exception\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
catch( IO_ERROR ioe )
|
catch( IO_ERROR& ioe )
|
||||||
{
|
{
|
||||||
printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) );
|
printf( "exception: %s\n", (const char*) ioe.errorText.ToUTF8() ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,18 @@
|
||||||
#define DIR_LIB_SOURCE_H_
|
#define DIR_LIB_SOURCE_H_
|
||||||
|
|
||||||
|
|
||||||
#include <sch_lib.h>
|
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <sch_lib.h>
|
||||||
|
|
||||||
|
|
||||||
|
/// This file extension is an implementation detail specific to this LIB_SOURCE
|
||||||
|
/// and to a corresponding LIB_SINK.
|
||||||
|
/// Core EESCHEMA should never have to see this.
|
||||||
|
#define SWEET_EXT ".part"
|
||||||
|
#define SWEET_EXTZ (sizeof(SWEET_EXT)-1)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct BY_REV
|
* struct BY_REV
|
||||||
|
|
|
@ -22,9 +22,14 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <memory> // std::auto_ptr
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
#include <sch_lib.h>
|
#include <sch_lib.h>
|
||||||
|
#include <sch_lpid.h>
|
||||||
|
#include <sch_part.h>
|
||||||
|
#include <sweet_lexer.h>
|
||||||
|
#include <sch_lib_table.h>
|
||||||
|
|
||||||
using namespace SCH;
|
using namespace SCH;
|
||||||
|
|
||||||
|
@ -44,9 +49,40 @@ LIB::~LIB()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PART* LIB::LookupPart( const LPID& aLPID ) throw( IO_ERROR )
|
PART* LIB::LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable ) throw( IO_ERROR )
|
||||||
{
|
{
|
||||||
return 0;
|
PART* part;
|
||||||
|
|
||||||
|
// If part not already cached
|
||||||
|
if( 1 /* @todo test cache */ )
|
||||||
|
{
|
||||||
|
// load it.
|
||||||
|
|
||||||
|
part = new PART( this, aLPID.GetPartName(), aLPID.GetRevision() );
|
||||||
|
|
||||||
|
std::auto_ptr<PART> wrapped( part );
|
||||||
|
|
||||||
|
source->ReadPart( &part->body, aLPID.GetPartName(), aLPID.GetRevision() );
|
||||||
|
|
||||||
|
#if defined(DEBUG)
|
||||||
|
const STRING& body = part->body;
|
||||||
|
printf( "body: %s", body.c_str() );
|
||||||
|
if( !body.size() || body[body.size()-1] != '\n' )
|
||||||
|
printf( "\n" );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SWEET_LEXER sw( part->body, wxString::FromUTF8("body") /* @todo have ReadPart give better source */ );
|
||||||
|
|
||||||
|
part->Parse( &sw, aLibTable );
|
||||||
|
|
||||||
|
|
||||||
|
// stuff the part into this LIBs cache:
|
||||||
|
// @todo
|
||||||
|
|
||||||
|
wrapped.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
return part;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,14 +26,14 @@
|
||||||
#define SCH_LIB_H_
|
#define SCH_LIB_H_
|
||||||
|
|
||||||
#include <utf8.h>
|
#include <utf8.h>
|
||||||
#include <kicad_exceptions.h>
|
#include <richio.h>
|
||||||
|
|
||||||
|
|
||||||
namespace SCH {
|
namespace SCH {
|
||||||
|
|
||||||
class LPID;
|
class LPID;
|
||||||
class PART;
|
class PART;
|
||||||
|
class LIB_TABLE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class LIB_SOURCE
|
* Class LIB_SOURCE
|
||||||
|
@ -69,7 +69,7 @@ protected: ///< derived classes must implement
|
||||||
* Function ReadPart
|
* Function ReadPart
|
||||||
* fetches @a aPartName's s-expression into @a aResult after clear()ing aResult.
|
* fetches @a aPartName's s-expression into @a aResult after clear()ing aResult.
|
||||||
*/
|
*/
|
||||||
virtual void ReadPart( STRING* aResult, const STRING& aPartName, const STRING& aRev = "" )
|
virtual void ReadPart( STR_UTF* aResult, const STRING& aPartName, const STRING& aRev = "" )
|
||||||
throw( IO_ERROR ) = 0;
|
throw( IO_ERROR ) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,7 +80,7 @@ protected: ///< derived classes must implement
|
||||||
* does not have a version string, then the most recent version is fetched.
|
* does not have a version string, then the most recent version is fetched.
|
||||||
* @param aResults receives the s-expressions
|
* @param aResults receives the s-expressions
|
||||||
*/
|
*/
|
||||||
virtual void ReadParts( STRINGS* aResults, const STRINGS& aPartNames )
|
virtual void ReadParts( STR_UTFS* aResults, const STRINGS& aPartNames )
|
||||||
throw( IO_ERROR ) = 0;
|
throw( IO_ERROR ) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -239,12 +239,15 @@ public:
|
||||||
* @param aLPID is the part to lookup. The logicalLibName can be empty in it
|
* @param aLPID is the part to lookup. The logicalLibName can be empty in it
|
||||||
* since yes, we know which LIB is in play.
|
* since yes, we know which LIB is in play.
|
||||||
*
|
*
|
||||||
|
* @param aLibTable is the LIB_TABLE view that is in effect for inheritance,
|
||||||
|
* and comes from the big containing SCHEMATIC object.
|
||||||
|
*
|
||||||
* @return PART* - The desired PART and will never be NULL. No ownership is
|
* @return PART* - The desired PART and will never be NULL. No ownership is
|
||||||
* given to caller. PARTs always reside in the cache that is a LIB.
|
* given to caller. PARTs always reside in the cache that is a LIB.
|
||||||
*
|
*
|
||||||
* @throw IO_ERROR if the part cannot be found or loaded.
|
* @throw IO_ERROR if the part cannot be found or loaded.
|
||||||
*/
|
*/
|
||||||
PART* LookupPart( const LPID& aLPID )
|
PART* LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable )
|
||||||
throw( IO_ERROR );
|
throw( IO_ERROR );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -315,13 +318,13 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
STRING fetch; // scratch, used to fetch things, grows to worst case size.
|
STR_UTF fetch; // scratch, used to fetch things, grows to worst case size.
|
||||||
STRINGS vfetch; // scratch, used to fetch things.
|
STR_UTFS vfetch; // scratch, used to fetch things.
|
||||||
|
|
||||||
STRING name;
|
STRING name;
|
||||||
LIB_SOURCE* source;
|
LIB_SOURCE* source;
|
||||||
LIB_SINK* sink;
|
LIB_SINK* sink;
|
||||||
STRING libraryURI;
|
// STRING libraryURI;
|
||||||
|
|
||||||
STRINGS categories;
|
STRINGS categories;
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR )
|
||||||
msg += row->logicalName;
|
msg += row->logicalName;
|
||||||
msg += '\'';
|
msg += '\'';
|
||||||
msg += " is a duplicate logical lib name";
|
msg += " is a duplicate logical lib name";
|
||||||
throw IO_ERROR( msg );
|
THROW_IO_ERROR( msg );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,53 +187,46 @@ STRINGS LIB_TABLE::GetLogicalLibs()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PART* LIB_TABLE::LookupPart( const LPID& aLogicalPartID, LIB* aLocalLib )
|
PART* LIB_TABLE::LookupPart( const LPID& aLPID, LIB* aLocalLib )
|
||||||
throw( IO_ERROR )
|
throw( IO_ERROR )
|
||||||
{
|
{
|
||||||
LIB* lib = lookupLib( aLogicalPartID, aLocalLib );
|
LIB* lib = lookupLib( aLPID, aLocalLib );
|
||||||
|
|
||||||
return lib->LookupPart( aLogicalPartID );
|
return lib->LookupPart( aLPID, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LIB* LIB_TABLE::lookupLib( const LPID& aLogicalPartID, LIB* aLocalLib )
|
LIB* LIB_TABLE::lookupLib( const LPID& aLPID, LIB* aFallBackLib )
|
||||||
throw( IO_ERROR )
|
throw( IO_ERROR )
|
||||||
{
|
{
|
||||||
if( aLocalLib )
|
if( aLPID.GetLogicalLib().size() )
|
||||||
{
|
{
|
||||||
return aLocalLib;
|
ROW* row = FindRow( aLPID.GetLogicalLib() );
|
||||||
}
|
if( !row )
|
||||||
else
|
|
||||||
{
|
|
||||||
const STRING& logName = aLogicalPartID.GetLogicalLib();
|
|
||||||
|
|
||||||
if( logName.size() )
|
|
||||||
{
|
{
|
||||||
ROW* row = FindRow( logName );
|
STRING msg = "lib table contains no logical lib '";
|
||||||
if( !row )
|
msg += aLPID.GetLogicalLib();
|
||||||
{
|
msg += '\'';
|
||||||
STRING msg = "Unable to find logical lib ";
|
THROW_IO_ERROR( msg );
|
||||||
msg += logName;
|
|
||||||
throw IO_ERROR( msg );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !row->lib )
|
|
||||||
{
|
|
||||||
loadLib( row );
|
|
||||||
}
|
|
||||||
|
|
||||||
assert( row->lib ); // loadLib() throws if cannot load
|
|
||||||
|
|
||||||
return row->lib;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if( !row->lib )
|
||||||
{
|
{
|
||||||
STRING msg = "No logicalLibName in LPID and no localLib";
|
loadLib( row );
|
||||||
throw IO_ERROR( msg );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert( row->lib ); // fix loadLib() to throw if cannot load
|
||||||
|
|
||||||
|
return row->lib;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return NULL; never get here
|
if( aFallBackLib )
|
||||||
|
{
|
||||||
|
return aFallBackLib;
|
||||||
|
}
|
||||||
|
|
||||||
|
STRING msg = "lookupLib() requires logicalLibName or a fallback lib";
|
||||||
|
THROW_IO_ERROR( msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -262,6 +255,7 @@ void LIB_TABLE::loadLib( ROW* aRow ) throw( IO_ERROR )
|
||||||
aRow->lib = new LIB( aRow->GetLogicalName(), source.release(), NULL );
|
aRow->lib = new LIB( aRow->GetLogicalName(), source.release(), NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
else if( !libType.compare( "schematic" ) )
|
else if( !libType.compare( "schematic" ) )
|
||||||
{
|
{
|
||||||
// @todo code and load SCHEMATIC_LIB_SOURCE
|
// @todo code and load SCHEMATIC_LIB_SOURCE
|
||||||
|
@ -276,6 +270,14 @@ void LIB_TABLE::loadLib( ROW* aRow ) throw( IO_ERROR )
|
||||||
{
|
{
|
||||||
// @todo code and load HTTP_LIB_SOURCE
|
// @todo code and load HTTP_LIB_SOURCE
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
STRING msg = "cannot load unknown libType: '";
|
||||||
|
msg += libType;
|
||||||
|
msg += '\'';
|
||||||
|
THROW_IO_ERROR( msg );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -334,44 +336,34 @@ bool LIB_TABLE::InsertRow( std::auto_ptr<ROW>& aRow, bool doReplace )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0 && defined(DEBUG)
|
#if 1 && defined(DEBUG)
|
||||||
|
|
||||||
// build this with a Debug CMAKE_BUILD_TYPE
|
// build this with a Debug CMAKE_BUILD_TYPE
|
||||||
|
|
||||||
void LIB_TABLE::Test()
|
void LIB_TABLE::Test()
|
||||||
{
|
{
|
||||||
// the null string is not really a legal DSN token since any duplicated
|
// A pair of double quotes alone, is not really a legal DSN token since
|
||||||
// double quote ("") is assumed to be a single double quote (").
|
// any duplicated double quote ("") is assumed to be a single double quote (")
|
||||||
// To pass an empty string, we can pass " " to (options " ")
|
// in any DSN lexer.
|
||||||
|
// To pass an empty string, we can pass " " to (options " "), or if you passed
|
||||||
|
// """" this would show up as "" with quotes present in the parser. The parser
|
||||||
|
// probably doesn't want a pair of double quotes, strlen() = 2.
|
||||||
SCH_LIB_TABLE_LEXER slr(
|
SCH_LIB_TABLE_LEXER slr(
|
||||||
"(lib_table \n"
|
"(lib_table \n"
|
||||||
" (lib (logical www) (type http) (full_uri http://kicad.org/libs) (options \" \"))\n"
|
" (lib (logical www) (type http) (full_uri http://kicad.org/libs) (options \" \"))\n"
|
||||||
" (lib (logical meparts) (type dir) (full_uri /tmp/eeschema-lib) (options \" \"))\n"
|
" (lib (logical meparts) (type dir) (full_uri /tmp/eeschema-lib) (options useVersioning))\n"
|
||||||
" (lib (logical old-project) (type schematic)(full_uri /tmp/old-schematic.sch) (options \" \"))\n"
|
" (lib (logical old-project) (type schematic)(full_uri /tmp/old-schematic.sch) (options \" \"))\n"
|
||||||
,
|
,
|
||||||
|
|
||||||
wxT( "inline text" ) // source
|
wxT( "inline text" ) // source
|
||||||
);
|
);
|
||||||
|
|
||||||
try
|
// read the "( lib_table" pair of tokens
|
||||||
{
|
slr.NextTok();
|
||||||
// read the "( lib_table" pair of tokens
|
slr.NextTok();
|
||||||
slr.NextTok();
|
|
||||||
slr.NextTok();
|
|
||||||
|
|
||||||
// parse the rest of input to slr
|
// parse the rest of input to slr
|
||||||
Parse( &slr );
|
Parse( &slr );
|
||||||
}
|
|
||||||
|
|
||||||
catch( std::exception& ex )
|
|
||||||
{
|
|
||||||
printf( "std::exception\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
catch( IO_ERROR ioe )
|
|
||||||
{
|
|
||||||
printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
STRING_FORMATTER sf;
|
STRING_FORMATTER sf;
|
||||||
|
|
||||||
|
@ -401,6 +393,11 @@ void LIB_TABLE::Test()
|
||||||
{
|
{
|
||||||
printf( "logicalName: %s\n", it->c_str() );
|
printf( "logicalName: %s\n", it->c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find a part
|
||||||
|
LPID lpid( "meparts:tigers/ears/rev10" );
|
||||||
|
|
||||||
|
LookupPart( lpid );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -408,7 +405,18 @@ int main( int argc, char** argv )
|
||||||
{
|
{
|
||||||
LIB_TABLE lib_table;
|
LIB_TABLE lib_table;
|
||||||
|
|
||||||
lib_table.Test();
|
try
|
||||||
|
{
|
||||||
|
// test exceptions:
|
||||||
|
// THROW_PARSE_ERROR( wxT("test problem"), wxT("input"), 23, 46 );
|
||||||
|
//THROW_IO_ERROR( wxT("io test") );
|
||||||
|
|
||||||
|
lib_table.Test();
|
||||||
|
}
|
||||||
|
catch( IO_ERROR& ioe )
|
||||||
|
{
|
||||||
|
printf( "%s\n", (const char*) ioe.errorText.ToUTF8() );
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -350,14 +350,12 @@ private:
|
||||||
* finds or loads a LIB based on @a aLogicalPartID or @a aFallBackLib.
|
* finds or loads a LIB based on @a aLogicalPartID or @a aFallBackLib.
|
||||||
* If the LIB is already loaded then it is returned as is, else it is loaded.
|
* If the LIB is already loaded then it is returned as is, else it is loaded.
|
||||||
*
|
*
|
||||||
* @param aLogicalPartID may hold the logicalLibName. If
|
* @param aLogicalPartID holds the partName and may also hold the logicalLibName. If
|
||||||
* logicalLibName is empty, then @a aLocalLib should not be NULL.
|
* logicalLibName is empty, then @a aFallBackLib should not be NULL.
|
||||||
*
|
*
|
||||||
* @param aLocalLib is used if not NULL, and should be supplied especiallly if
|
* @param aFallBackLib is used only if aLogicalPartID has an empty logicalLibName.
|
||||||
* aLogicalPartID has an empty logicalLibName. This is for the case when
|
* This is for the case when an LPID has no logicalLibName because the LPID is using
|
||||||
* a partName must come from the same LIB as the referring content.
|
* a partName from the same LIB as was the referring content.
|
||||||
* For example, a PART extends another PART in the same LIB and the extends
|
|
||||||
* LPID has no logical lib name.
|
|
||||||
*
|
*
|
||||||
* @return LIB* - this will never be NULL, and no ownership is transfered because
|
* @return LIB* - this will never be NULL, and no ownership is transfered because
|
||||||
* all LIBs live in the LIB_TABLEs. You only get to point to them in some LIB_TABLE.
|
* all LIBs live in the LIB_TABLEs. You only get to point to them in some LIB_TABLE.
|
||||||
|
@ -365,7 +363,7 @@ private:
|
||||||
*
|
*
|
||||||
* @throw IO_ERROR if any problem occurs or if the LIB cannot be found or cannot be loaded.
|
* @throw IO_ERROR if any problem occurs or if the LIB cannot be found or cannot be loaded.
|
||||||
*/
|
*/
|
||||||
LIB* lookupLib( const LPID& aLogicalPartID, LIB* aLocalLib = NULL ) throw( IO_ERROR );
|
LIB* lookupLib( const LPID& aLogicalPartID, LIB* aFallBackLib = NULL ) throw( IO_ERROR );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function loadLib
|
* Function loadLib
|
||||||
|
|
|
@ -114,6 +114,7 @@ int LPID::Parse( const STRING& aLPID )
|
||||||
logical.clear();
|
logical.clear();
|
||||||
category.clear();
|
category.clear();
|
||||||
baseName.clear();
|
baseName.clear();
|
||||||
|
partName.clear();
|
||||||
revision.clear();
|
revision.clear();
|
||||||
|
|
||||||
const char* rev = EndsWithRev( aLPID );
|
const char* rev = EndsWithRev( aLPID );
|
||||||
|
@ -183,7 +184,7 @@ LPID::LPID( const STRING& aLPID ) throw( PARSE_ERROR )
|
||||||
|
|
||||||
if( offset != -1 )
|
if( offset != -1 )
|
||||||
{
|
{
|
||||||
throw PARSE_ERROR(
|
THROW_PARSE_ERROR(
|
||||||
_( "Illegal character found in LPID string" ),
|
_( "Illegal character found in LPID string" ),
|
||||||
wxConvertMB2WX( aLPID.c_str() ),
|
wxConvertMB2WX( aLPID.c_str() ),
|
||||||
0,
|
0,
|
||||||
|
@ -193,12 +194,6 @@ LPID::LPID( const STRING& aLPID ) throw( PARSE_ERROR )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const STRING& LPID::GetLogicalLib() const
|
|
||||||
{
|
|
||||||
return logical;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int LPID::SetLogicalLib( const STRING& aLogical )
|
int LPID::SetLogicalLib( const STRING& aLogical )
|
||||||
{
|
{
|
||||||
int offset = okLogical( aLogical );
|
int offset = okLogical( aLogical );
|
||||||
|
@ -210,63 +205,49 @@ int LPID::SetLogicalLib( const STRING& aLogical )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const STRING& LPID::GetCategory() const
|
|
||||||
{
|
|
||||||
return category;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int LPID::SetCategory( const STRING& aCategory )
|
int LPID::SetCategory( const STRING& aCategory )
|
||||||
{
|
{
|
||||||
int offset = okCategory( aCategory );
|
int offset = okCategory( aCategory );
|
||||||
if( offset == -1 )
|
if( offset == -1 )
|
||||||
{
|
{
|
||||||
category = aCategory;
|
category = aCategory;
|
||||||
|
|
||||||
|
// set the partName too
|
||||||
|
if( category.size() )
|
||||||
|
{
|
||||||
|
partName = category;
|
||||||
|
partName += '/';
|
||||||
|
partName += baseName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
partName = baseName;
|
||||||
|
|
||||||
}
|
}
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const STRING& LPID::GetBaseName() const
|
|
||||||
{
|
|
||||||
return baseName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int LPID::SetBaseName( const STRING& aBaseName )
|
int LPID::SetBaseName( const STRING& aBaseName )
|
||||||
{
|
{
|
||||||
int offset = okBase( aBaseName );
|
int offset = okBase( aBaseName );
|
||||||
if( offset == -1 )
|
if( offset == -1 )
|
||||||
{
|
{
|
||||||
baseName = aBaseName;
|
baseName = aBaseName;
|
||||||
|
|
||||||
|
// set the partName too
|
||||||
|
if( category.size() )
|
||||||
|
{
|
||||||
|
partName = category;
|
||||||
|
partName += '/';
|
||||||
|
partName += baseName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
partName = baseName;
|
||||||
}
|
}
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
STRING LPID::GetPartName() const
|
|
||||||
{
|
|
||||||
STRING ret;
|
|
||||||
|
|
||||||
// return [category/]baseName
|
|
||||||
if( category.size() )
|
|
||||||
{
|
|
||||||
ret += category;
|
|
||||||
ret += '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
ret += baseName;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const STRING& LPID::GetRevision() const
|
|
||||||
{
|
|
||||||
return revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int LPID::SetRevision( const STRING& aRevision )
|
int LPID::SetRevision( const STRING& aRevision )
|
||||||
{
|
{
|
||||||
int offset = okRevision( aRevision );
|
int offset = okRevision( aRevision );
|
||||||
|
@ -306,7 +287,7 @@ STRING LPID::Format() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 1 && defined(DEBUG)
|
#if 0 && defined(DEBUG)
|
||||||
|
|
||||||
// build this with Debug CMAKE_BUILD_TYPE
|
// build this with Debug CMAKE_BUILD_TYPE
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#define SCH_LPID_H_
|
#define SCH_LPID_H_
|
||||||
|
|
||||||
#include <utf8.h>
|
#include <utf8.h>
|
||||||
#include <kicad_exceptions.h>
|
#include <richio.h>
|
||||||
|
|
||||||
namespace SCH {
|
namespace SCH {
|
||||||
|
|
||||||
|
@ -84,7 +84,10 @@ public:
|
||||||
* for this portion since it comes from the library table and is considered
|
* for this portion since it comes from the library table and is considered
|
||||||
* read only here.
|
* read only here.
|
||||||
*/
|
*/
|
||||||
const STRING& GetLogicalLib() const;
|
const STRING& GetLogicalLib() const
|
||||||
|
{
|
||||||
|
return logical;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function SetCategory
|
* Function SetCategory
|
||||||
|
@ -100,7 +103,10 @@ public:
|
||||||
* returns the category of this part id, "passives" in the example at the
|
* returns the category of this part id, "passives" in the example at the
|
||||||
* top of the class description.
|
* top of the class description.
|
||||||
*/
|
*/
|
||||||
const STRING& GetCategory() const;
|
const STRING& GetCategory() const
|
||||||
|
{
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function SetCategory
|
* Function SetCategory
|
||||||
|
@ -116,7 +122,10 @@ public:
|
||||||
* Function GetBaseName
|
* Function GetBaseName
|
||||||
* returns the part name without the category.
|
* returns the part name without the category.
|
||||||
*/
|
*/
|
||||||
const STRING& GetBaseName() const;
|
const STRING& GetBaseName() const
|
||||||
|
{
|
||||||
|
return baseName;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function SetBaseName
|
* Function SetBaseName
|
||||||
|
@ -131,20 +140,19 @@ public:
|
||||||
* Function GetPartName
|
* Function GetPartName
|
||||||
* returns the part name, i.e. category/baseName without revision.
|
* returns the part name, i.e. category/baseName without revision.
|
||||||
*/
|
*/
|
||||||
STRING GetPartName() const;
|
const STRING& GetPartName() const
|
||||||
|
{
|
||||||
/**
|
return partName;
|
||||||
* Function SetBaseName
|
}
|
||||||
* overrides the part name portion of the LPID to @a aPartName
|
|
||||||
not really needed, partname is an agreggate anyway, just parse a new one.
|
|
||||||
void SetPartName( const STRING& aPartName );
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetRevision
|
* Function GetRevision
|
||||||
* returns the revision portion of the LPID.
|
* returns the revision portion of the LPID.
|
||||||
*/
|
*/
|
||||||
const STRING& GetRevision() const;
|
const STRING& GetRevision() const
|
||||||
|
{
|
||||||
|
return revision;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function SetRevision
|
* Function SetRevision
|
||||||
|
@ -171,6 +179,7 @@ protected:
|
||||||
STRING category; ///< or empty
|
STRING category; ///< or empty
|
||||||
STRING baseName; ///< without category
|
STRING baseName; ///< without category
|
||||||
STRING revision; ///< "revN[N..]" or empty
|
STRING revision; ///< "revN[N..]" or empty
|
||||||
|
STRING partName; ///< cannot be set directory, set via SetBaseName() & SetCategory()
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SCH
|
} // namespace SCH
|
||||||
|
|
|
@ -22,12 +22,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "sch_part.h"
|
#include <sch_part.h>
|
||||||
|
#include <sweet_lexer.h>
|
||||||
|
#include <wx/wx.h> // _()
|
||||||
|
|
||||||
|
|
||||||
using namespace SCH;
|
using namespace SCH;
|
||||||
|
|
||||||
void PART::Parse( LIB* aLexer ) throw( PARSE_ERROR )
|
|
||||||
|
void PART::Parse( SWEET_LEXER* aLexer, LIB_TABLE* aTable ) throw( PARSE_ERROR )
|
||||||
{
|
{
|
||||||
|
// Wayne's world, if he still wants it.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,31 @@
|
||||||
|
|
||||||
#include <sch_lib.h>
|
#include <sch_lib.h>
|
||||||
|
|
||||||
|
class SWEET_LEXER;
|
||||||
|
|
||||||
namespace SCH {
|
namespace SCH {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum PartBit
|
||||||
|
* is a set of bit positions that can be used to create flag bits within
|
||||||
|
* PART::contains to indicate what state the PART is in and what it contains, i.e.
|
||||||
|
* whether the PART has been parsed, and what the PART contains, categorically.
|
||||||
|
*/
|
||||||
|
enum PartBit
|
||||||
|
{
|
||||||
|
PARSED, ///< have parsed this part already, otherwise 'body' text must be parsed
|
||||||
|
EXTENDS, ///< saw and "extends" keyword, inheriting from another PART
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Function PB
|
||||||
|
/// is a PartBit shifter for PART::contains field.
|
||||||
|
static inline const int PB( PartBit oneBitOnly )
|
||||||
|
{
|
||||||
|
return ( 1 << oneBitOnly );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class PART
|
* Class PART
|
||||||
* will have to be unified with what Wayne is doing. I want a separate copy
|
* will have to be unified with what Wayne is doing. I want a separate copy
|
||||||
|
@ -47,19 +69,23 @@ class PART
|
||||||
/// be done by PARTS_LIST, a class derived from LIB.
|
/// be done by PARTS_LIST, a class derived from LIB.
|
||||||
friend class LIB;
|
friend class LIB;
|
||||||
|
|
||||||
|
|
||||||
/// a private constructor, only a LIB can instantiate a PART.
|
/// a private constructor, only a LIB can instantiate a PART.
|
||||||
PART() {}
|
PART( LIB* aOwner, const STRING& aPartName, const STRING& aRevision ) :
|
||||||
|
owner( aOwner ),
|
||||||
|
contains( 0 ),
|
||||||
|
partName( aPartName ),
|
||||||
|
revision( aRevision )
|
||||||
|
{}
|
||||||
|
|
||||||
protected: // not likely to have C++ descendants, but protected none-the-less.
|
protected: // not likely to have C++ descendants, but protected none-the-less.
|
||||||
|
|
||||||
bool parsed; ///< true if the body as been parsed already.
|
|
||||||
|
|
||||||
LIB* owner; ///< which LIB am I a part of (pun if you want)
|
LIB* owner; ///< which LIB am I a part of (pun if you want)
|
||||||
|
int contains; ///< has bits from Enum PartParts
|
||||||
|
|
||||||
STRING extends; ///< LPID of base part
|
STRING extends; ///< LPID of base part
|
||||||
|
|
||||||
STRING name; ///< example "passives/R", immutable.
|
STRING partName; ///< example "passives/R", immutable.
|
||||||
|
STRING revision; // @todo need a single search key, this won't do.
|
||||||
|
|
||||||
/// s-expression text for the part, initially empty, and read in as this part
|
/// s-expression text for the part, initially empty, and read in as this part
|
||||||
/// actually becomes cached in RAM.
|
/// actually becomes cached in RAM.
|
||||||
|
@ -81,7 +107,6 @@ protected: // not likely to have C++ descendants, but protected none-the-le
|
||||||
|
|
||||||
// lots of other stuff, like the mandatory properties.
|
// lots of other stuff, like the mandatory properties.
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,7 +116,6 @@ public:
|
||||||
*/
|
*/
|
||||||
void Inherit( const PART& aBasePart );
|
void Inherit( const PART& aBasePart );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Owner
|
* Function Owner
|
||||||
* returns the LIB* owner of this part.
|
* returns the LIB* owner of this part.
|
||||||
|
@ -100,12 +124,23 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Parse
|
* Function Parse
|
||||||
* translates the \a body string into a binary form that is represented
|
* translates a Sweet string into a binary form that is represented
|
||||||
* by the normal fields of this class. Parse is expected to call Inherit()
|
* by the normal fields of this class. Parse is expected to call Inherit()
|
||||||
* if this part extends any other.
|
* if this part extends any other.
|
||||||
|
*
|
||||||
|
* @param aLexer is an instance of SWEET_LEXER, rewound at the first line.
|
||||||
|
*
|
||||||
|
* @param aLibTable is the LIB_TABLE view that is in effect for inheritance,
|
||||||
|
* and comes from the big containing SCHEMATIC object.
|
||||||
*/
|
*/
|
||||||
void Parse( LIB* aLexer ) throw( PARSE_ERROR );
|
void Parse( SWEET_LEXER* aLexer, LIB_TABLE* aTable ) throw( PARSE_ERROR );
|
||||||
|
|
||||||
|
/*
|
||||||
|
void SetBody( const STR_UTF& aSExpression )
|
||||||
|
{
|
||||||
|
body = aSExpression;
|
||||||
|
}
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace PART
|
} // namespace PART
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
part
|
||||||
|
extends
|
25
new/utf8.h
25
new/utf8.h
|
@ -13,14 +13,19 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type STRING
|
* Type STRING
|
||||||
* holds a sequence of 8 bit bytes that represent a sequence
|
* holds a sequence of 8 bit bytes that represent a sequence of variable
|
||||||
* of variable multi-byte international characters, with unspecified encoding.
|
* length multi-byte international characters, with unspecified encoding.
|
||||||
*/
|
*/
|
||||||
typedef std::string STRING;
|
typedef std::string STRING;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type STRINGS
|
||||||
|
* is an "array like" list of STRINGs
|
||||||
|
*/
|
||||||
|
typedef std::deque<STRING> STRINGS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type STRING_UTF8
|
* Type STR_UTF
|
||||||
* holds a UTF8 encoded sequence of 8 bit bytes that represent a sequence
|
* holds a UTF8 encoded sequence of 8 bit bytes that represent a sequence
|
||||||
* of variable multi-byte international characters. UTF8 is the chosen encoding
|
* of variable multi-byte international characters. UTF8 is the chosen encoding
|
||||||
* for all Kicad data files so that they can be transported from one nation to another
|
* for all Kicad data files so that they can be transported from one nation to another
|
||||||
|
@ -29,19 +34,15 @@ typedef std::string STRING;
|
||||||
* Filenames may be encoded on disk using an encoding chosen by the host operating
|
* Filenames may be encoded on disk using an encoding chosen by the host operating
|
||||||
* system. Nonetheless, Kicad data file _content_ is always UTF8 encoded, regardless
|
* system. Nonetheless, Kicad data file _content_ is always UTF8 encoded, regardless
|
||||||
* of host operating system.
|
* of host operating system.
|
||||||
* STRING_UTF is UTF8 encoded, by definition.
|
* STR_UTF is UTF8 encoded, by definition.
|
||||||
*/
|
*/
|
||||||
typedef STRING STRING_UTF8;
|
typedef STRING STR_UTF;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type STRINGS_UTF8
|
* Type STR_UTFS
|
||||||
* is an "array like" list of STRING_UTF8s
|
* is an "array like" list of STR_UTFs
|
||||||
*/
|
*/
|
||||||
typedef std::deque<STRING> STRINGS_UTF8;
|
typedef std::deque<STRING> STR_UTFS;
|
||||||
|
|
||||||
typedef std::deque<STRING> STRINGS;
|
|
||||||
|
|
||||||
|
|
||||||
/** @} string_types */
|
/** @} string_types */
|
||||||
|
|
||||||
|
|
|
@ -542,7 +542,7 @@ void SPECCTRA_DB::ThrowIOError( const wxChar* fmt, ... ) throw( IO_ERROR )
|
||||||
errText.PrintfV( fmt, args );
|
errText.PrintfV( fmt, args );
|
||||||
va_end( args );
|
va_end( args );
|
||||||
|
|
||||||
throw IO_ERROR( errText );
|
THROW_IO_ERROR( errText );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue