Parse generator_version and improve error output on mismatch
Also bump symbol format version for generator_version
This commit is contained in:
parent
b13e244dc5
commit
4ff127b452
|
@ -51,3 +51,5 @@ repeat
|
|||
incrx
|
||||
incry
|
||||
incrlabel
|
||||
generator
|
||||
generator_version
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
|
||||
#include <charconv>
|
||||
#include <fmt/format.h>
|
||||
#include <wx/base64.h>
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/log.h>
|
||||
|
@ -53,6 +54,7 @@ public:
|
|||
|
||||
private:
|
||||
int m_requiredVersion;
|
||||
wxString m_generatorVersion;
|
||||
|
||||
/**
|
||||
* Parse the data specified at the very beginning of the file, like version and the
|
||||
|
@ -209,6 +211,16 @@ void DRAWING_SHEET_PARSER::Parse( DS_DATA_MODEL* aLayout )
|
|||
parseHeader( token );
|
||||
aLayout->SetFileFormatVersionAtLoad( m_requiredVersion );
|
||||
|
||||
auto checkVersion =
|
||||
[&]()
|
||||
{
|
||||
if( m_requiredVersion > SEXPR_WORKSHEET_FILE_VERSION )
|
||||
{
|
||||
throw FUTURE_FORMAT_ERROR( fmt::format( "{}", m_requiredVersion ),
|
||||
m_generatorVersion );
|
||||
}
|
||||
};
|
||||
|
||||
for( token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
|
||||
{
|
||||
if( token == T_LEFT )
|
||||
|
@ -216,7 +228,22 @@ void DRAWING_SHEET_PARSER::Parse( DS_DATA_MODEL* aLayout )
|
|||
|
||||
switch( token )
|
||||
{
|
||||
case T_generator:
|
||||
// (generator "genname"); we don't care about it at the moment.
|
||||
NeedSYMBOL();
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_generator_version:
|
||||
NextTok();
|
||||
m_generatorVersion = FromUTF8();
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_setup: // Defines default values for graphic items
|
||||
// Check the version here, because the generator and generator_version (if available)
|
||||
// will have been parsed by now given the order the formatter writes them in
|
||||
checkVersion();
|
||||
parseSetup( aLayout );
|
||||
break;
|
||||
|
||||
|
@ -285,21 +312,12 @@ void DRAWING_SHEET_PARSER::parseHeader( T aHeaderType )
|
|||
{
|
||||
m_requiredVersion = parseInt();
|
||||
|
||||
if( m_requiredVersion > SEXPR_WORKSHEET_FILE_VERSION )
|
||||
throw FUTURE_FORMAT_ERROR( FromUTF8() );
|
||||
|
||||
NeedRIGHT();
|
||||
}
|
||||
else
|
||||
{
|
||||
Expecting( T_version );
|
||||
}
|
||||
|
||||
// Ignore generator info.
|
||||
NeedLEFT();
|
||||
NeedSYMBOL();
|
||||
NeedSYMBOL();
|
||||
NeedRIGHT();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -94,22 +94,36 @@ void PARSE_ERROR::init( const wxString& aProblem, const char* aThrowersFile,
|
|||
}
|
||||
|
||||
|
||||
void FUTURE_FORMAT_ERROR::init( const wxString& aRequiredVersion )
|
||||
void FUTURE_FORMAT_ERROR::init( const wxString& aRequiredVersion,
|
||||
const wxString& aRequiredGenerator )
|
||||
{
|
||||
requiredVersion = aRequiredVersion;
|
||||
requiredGenerator = aRequiredGenerator;
|
||||
|
||||
problem.Printf( _( "KiCad was unable to open this file because it was created with a more "
|
||||
"recent version than the one you are running.\n\n"
|
||||
"To open it you will need to upgrade KiCad to a version dated %s or "
|
||||
"later." ),
|
||||
aRequiredVersion );
|
||||
if( requiredGenerator.IsEmpty() )
|
||||
{
|
||||
problem.Printf( _( "KiCad was unable to open this file because it was created with a more "
|
||||
"recent version than the one you are running.\n\n"
|
||||
"To open it you will need to upgrade KiCad to a version dated %s or "
|
||||
"later." ),
|
||||
aRequiredVersion );
|
||||
}
|
||||
else
|
||||
{
|
||||
problem.Printf( _( "KiCad was unable to open this file because it was created with a more "
|
||||
"recent version than the one you are running.\n\n"
|
||||
"To open it you will need to upgrade KiCad to version %s or "
|
||||
"later (file format dated %s or later)." ),
|
||||
aRequiredGenerator, aRequiredVersion );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FUTURE_FORMAT_ERROR::FUTURE_FORMAT_ERROR( const wxString& aRequiredVersion ) :
|
||||
FUTURE_FORMAT_ERROR::FUTURE_FORMAT_ERROR( const wxString& aRequiredVersion,
|
||||
const wxString& aRequiredGenerator ) :
|
||||
PARSE_ERROR()
|
||||
{
|
||||
init( aRequiredVersion );
|
||||
init( aRequiredVersion, aRequiredGenerator );
|
||||
|
||||
lineNumber = 0;
|
||||
byteIndex = 0;
|
||||
|
@ -117,17 +131,19 @@ FUTURE_FORMAT_ERROR::FUTURE_FORMAT_ERROR( const wxString& aRequiredVersion ) :
|
|||
|
||||
|
||||
FUTURE_FORMAT_ERROR::FUTURE_FORMAT_ERROR( const PARSE_ERROR& aParseError,
|
||||
const wxString& aRequiredVersion ) :
|
||||
const wxString& aRequiredVersion,
|
||||
const wxString& aRequiredGenerator ) :
|
||||
PARSE_ERROR()
|
||||
{
|
||||
if( const FUTURE_FORMAT_ERROR* ffe = dynamic_cast<const FUTURE_FORMAT_ERROR*>( &aParseError ) )
|
||||
{
|
||||
requiredVersion = ffe->requiredVersion;
|
||||
requiredGenerator = ffe->requiredGenerator;
|
||||
problem = ffe->Problem();
|
||||
}
|
||||
else
|
||||
{
|
||||
init( aRequiredVersion );
|
||||
init( aRequiredVersion, aRequiredGenerator );
|
||||
|
||||
if( !aParseError.Problem().IsEmpty() )
|
||||
problem += wxS( "\n\n" ) + _( "Full error text:" ) + wxS( "\n" ) + aParseError.Problem();
|
||||
|
|
|
@ -136,6 +136,7 @@ free
|
|||
full
|
||||
general
|
||||
generator
|
||||
generator_version
|
||||
generated
|
||||
grid_origin
|
||||
group
|
||||
|
|
|
@ -48,7 +48,8 @@
|
|||
//#define SEXPR_SYMBOL_LIB_FILE_VERSION 20220331 // Text colors.
|
||||
//#define SEXPR_SYMBOL_LIB_FILE_VERSION 20220914 // Symbol unit display names.
|
||||
//#define SEXPR_SYMBOL_LIB_FILE_VERSION 20220914 // Don't save property ID
|
||||
#define SEXPR_SYMBOL_LIB_FILE_VERSION 20230620 // ki_description -> Description Field
|
||||
//#define SEXPR_SYMBOL_LIB_FILE_VERSION 20230620 // ki_description -> Description Field
|
||||
#define SEXPR_SYMBOL_LIB_FILE_VERSION 20231120 // generator_version; V8 cleanups
|
||||
|
||||
/**
|
||||
* Schematic file version.
|
||||
|
@ -100,4 +101,5 @@
|
|||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20230409 // Add exclude_from_sim markup
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20230620 // ki_description -> Description Field
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20230808 // Move Sim.Enable field to exclude_from_sim attr
|
||||
#define SEXPR_SCHEMATIC_FILE_VERSION 20230819 // Allow multiple library symbol inheritance depth.
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20230819 // Allow multiple library symbol inheritance depth.
|
||||
#define SEXPR_SCHEMATIC_FILE_VERSION 20231120 // generator_version; V8 cleanups
|
||||
|
|
|
@ -91,7 +91,7 @@ void SCH_SEXPR_PLUGIN_CACHE::Save( const std::optional<bool>& aOpt )
|
|||
// Write through symlinks, don't replace them.
|
||||
wxFileName fn = GetRealFile();
|
||||
|
||||
auto formatter = std::make_unique<FILE_OUTPUTFORMATTER>( fn.GetFullPath() );
|
||||
auto formatter = std::make_unique<PRETTIFIED_FILE_OUTPUTFORMATTER>( fn.GetFullPath() );
|
||||
|
||||
formatter->Print( 0, "(kicad_symbol_lib (version %d) (generator \"kicad_symbol_editor\") (generator_version \"%s\")\n",
|
||||
SEXPR_SYMBOL_LIB_FILE_VERSION, GetMajorMinorVersion().c_str().AsChar() );
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
// base64 code.
|
||||
#include <charconv>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#define wxUSE_BASE64 1
|
||||
#include <wx/base64.h>
|
||||
#include <wx/mstream.h>
|
||||
|
@ -141,6 +142,20 @@ void SCH_SEXPR_PARSER::ParseLib( LIB_SYMBOL_MAP& aSymbolLibMap )
|
|||
NextTok();
|
||||
parseHeader( T_kicad_symbol_lib, SEXPR_SYMBOL_LIB_FILE_VERSION );
|
||||
|
||||
bool versionChecked = false;
|
||||
|
||||
auto checkVersion =
|
||||
[&]()
|
||||
{
|
||||
if( !versionChecked && m_requiredVersion > SEXPR_SYMBOL_LIB_FILE_VERSION )
|
||||
{
|
||||
throw FUTURE_FORMAT_ERROR( fmt::format( "{}", m_requiredVersion ),
|
||||
m_generatorVersion );
|
||||
}
|
||||
|
||||
versionChecked = true;
|
||||
};
|
||||
|
||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
{
|
||||
if( token != T_LEFT )
|
||||
|
@ -148,16 +163,53 @@ void SCH_SEXPR_PARSER::ParseLib( LIB_SYMBOL_MAP& aSymbolLibMap )
|
|||
|
||||
token = NextTok();
|
||||
|
||||
if( token == T_symbol )
|
||||
switch( token )
|
||||
{
|
||||
case T_generator:
|
||||
// (generator "genname"); we don't care about it at the moment.
|
||||
NeedSYMBOL();
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_host:
|
||||
{
|
||||
// (host eeschema ["5.99"]); old version of generator token
|
||||
NeedSYMBOL();
|
||||
|
||||
// Really old versions also included a host version
|
||||
if( m_requiredVersion < 20200827 )
|
||||
NeedSYMBOL();
|
||||
|
||||
NeedRIGHT();
|
||||
break;
|
||||
}
|
||||
|
||||
case T_generator_version:
|
||||
{
|
||||
NextTok();
|
||||
m_generatorVersion = FromUTF8();
|
||||
NeedRIGHT();
|
||||
|
||||
// If the format includes a generator version, by this point we have enough info to
|
||||
// do the version check here
|
||||
checkVersion();
|
||||
break;
|
||||
}
|
||||
|
||||
case T_symbol:
|
||||
{
|
||||
// By the time we get to the first symbol, we can check the version
|
||||
checkVersion();
|
||||
|
||||
m_unit = 1;
|
||||
m_convert = 1;
|
||||
LIB_SYMBOL* symbol = parseLibSymbol( aSymbolLibMap );
|
||||
aSymbolLibMap[symbol->GetName()] = symbol;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Expecting( "symbol" );
|
||||
|
||||
default:
|
||||
Expecting( "symbol, generator, or generator_version" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -740,30 +792,11 @@ void SCH_SEXPR_PARSER::parseHeader( TSCHEMATIC_T::T aHeaderType, int aFileVersio
|
|||
if( tok == T_version )
|
||||
{
|
||||
m_requiredVersion = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
|
||||
|
||||
if( m_requiredVersion > aFileVersion )
|
||||
throw FUTURE_FORMAT_ERROR( FromUTF8() );
|
||||
|
||||
NeedRIGHT();
|
||||
|
||||
// Skip the host name and host build version information.
|
||||
NeedLEFT();
|
||||
NeedSYMBOL();
|
||||
NeedSYMBOL();
|
||||
|
||||
if( m_requiredVersion < 20200827 )
|
||||
NeedSYMBOL();
|
||||
|
||||
NeedRIGHT();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_requiredVersion = aFileVersion;
|
||||
|
||||
// Skip the host name and host build version information.
|
||||
NeedSYMBOL();
|
||||
NeedSYMBOL();
|
||||
NeedRIGHT();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2379,6 +2412,16 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyableOnly,
|
|||
|
||||
bool fileHasUuid = false;
|
||||
|
||||
auto checkVersion =
|
||||
[&]()
|
||||
{
|
||||
if( m_requiredVersion > SEXPR_SCHEMATIC_FILE_VERSION )
|
||||
{
|
||||
throw FUTURE_FORMAT_ERROR( fmt::format( "{}", m_requiredVersion ),
|
||||
m_generatorVersion );
|
||||
}
|
||||
};
|
||||
|
||||
T token;
|
||||
|
||||
if( !aIsCopyableOnly )
|
||||
|
@ -2395,6 +2438,10 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyableOnly,
|
|||
// to generate one for the root schematic for instance paths.
|
||||
if( m_requiredVersion < 20210406 )
|
||||
m_rootUuid = screen->GetUuid();
|
||||
|
||||
// Prior to version 20231120, generator_version was not present, so check the date here
|
||||
if( m_requiredVersion < 20231120 )
|
||||
checkVersion();
|
||||
}
|
||||
|
||||
screen->SetFileFormatVersionAtLoad( m_requiredVersion );
|
||||
|
@ -2416,6 +2463,32 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyableOnly,
|
|||
|
||||
switch( token )
|
||||
{
|
||||
case T_generator:
|
||||
// (generator "genname"); we don't care about it at the moment.
|
||||
NeedSYMBOL();
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_host:
|
||||
{
|
||||
// (host eeschema ["5.99"]); old version of generator token
|
||||
NeedSYMBOL();
|
||||
|
||||
// Really old versions also included a host version
|
||||
if( m_requiredVersion < 20200827 )
|
||||
NeedSYMBOL();
|
||||
|
||||
NeedRIGHT();
|
||||
break;
|
||||
}
|
||||
|
||||
case T_generator_version:
|
||||
NextTok();
|
||||
m_generatorVersion = FromUTF8();
|
||||
NeedRIGHT();
|
||||
checkVersion();
|
||||
break;
|
||||
|
||||
case T_uuid:
|
||||
NeedSYMBOL();
|
||||
screen->m_uuid = parseKIID();
|
||||
|
|
|
@ -207,6 +207,7 @@ private:
|
|||
void parseBusAlias( SCH_SCREEN* aScreen );
|
||||
|
||||
int m_requiredVersion; ///< Set to the symbol library file version required.
|
||||
wxString m_generatorVersion;
|
||||
int m_unit; ///< The current unit being parsed.
|
||||
int m_convert; ///< The current body style being parsed.
|
||||
wxString m_symbolName; ///< The current symbol name.
|
||||
|
|
|
@ -42,11 +42,14 @@ fill
|
|||
font
|
||||
footprint
|
||||
free
|
||||
generator
|
||||
generator_version
|
||||
global_label
|
||||
hide
|
||||
hierarchical_label
|
||||
hint_alt_swap
|
||||
hint_pin_swap
|
||||
host
|
||||
href
|
||||
id
|
||||
image
|
||||
|
|
|
@ -174,13 +174,17 @@ protected:
|
|||
*/
|
||||
struct KICOMMON_API FUTURE_FORMAT_ERROR : public PARSE_ERROR
|
||||
{
|
||||
wxString requiredVersion; ///< version or date of KiCad required to open file
|
||||
wxString requiredVersion; ///< Date of KiCad file format required to open file
|
||||
wxString requiredGenerator; ///< Version of KiCad required to open file
|
||||
|
||||
FUTURE_FORMAT_ERROR( const wxString& aRequiredVersion );
|
||||
FUTURE_FORMAT_ERROR( const PARSE_ERROR& aParseError, const wxString& aRequiredVersion );
|
||||
FUTURE_FORMAT_ERROR( const wxString& aRequiredVersion,
|
||||
const wxString& aRequiredGenerator = wxEmptyString );
|
||||
FUTURE_FORMAT_ERROR( const PARSE_ERROR& aParseError, const wxString& aRequiredVersion,
|
||||
const wxString& aRequiredGenerator = wxEmptyString );
|
||||
~FUTURE_FORMAT_ERROR() throw () {}
|
||||
|
||||
void init( const wxString& aRequiredVersion );
|
||||
void init( const wxString& aRequiredVersion,
|
||||
const wxString& aRequiredGenerator = wxEmptyString );
|
||||
};
|
||||
|
||||
/** @} exception_types */
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <charconv>
|
||||
#include <confirm.h>
|
||||
#include <macros.h>
|
||||
#include <fmt/format.h>
|
||||
#include <title_block.h>
|
||||
#include <trigo.h>
|
||||
|
||||
|
@ -877,6 +878,16 @@ BOARD* PCB_PARSER::parseBOARD_unchecked()
|
|||
|
||||
parseHeader();
|
||||
|
||||
auto checkVersion =
|
||||
[&]()
|
||||
{
|
||||
if( m_requiredVersion > SEXPR_BOARD_FILE_VERSION )
|
||||
{
|
||||
throw FUTURE_FORMAT_ERROR( fmt::format( "{}", m_requiredVersion ),
|
||||
m_generatorVersion );
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<BOARD_ITEM*> bulkAddedItems;
|
||||
BOARD_ITEM* item = nullptr;
|
||||
|
||||
|
@ -911,7 +922,23 @@ BOARD* PCB_PARSER::parseBOARD_unchecked()
|
|||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_generator_version:
|
||||
{
|
||||
NeedSYMBOL();
|
||||
m_generatorVersion = FromUTF8();
|
||||
NeedRIGHT();
|
||||
|
||||
// If the format includes a generator version, by this point we have enough info to
|
||||
// do the version check here
|
||||
checkVersion();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case T_general:
|
||||
// Do another version check here, for older files that do not include generator_version
|
||||
checkVersion();
|
||||
|
||||
parseGeneralSection();
|
||||
break;
|
||||
|
||||
|
@ -1248,16 +1275,16 @@ void PCB_PARSER::parseHeader()
|
|||
if( tok == T_version )
|
||||
{
|
||||
m_requiredVersion = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
|
||||
m_tooRecent = ( m_requiredVersion > SEXPR_BOARD_FILE_VERSION );
|
||||
NeedRIGHT();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_requiredVersion = 20201115; // Last version before we started writing version #s
|
||||
// in footprint files as well as board files.
|
||||
m_tooRecent = ( m_requiredVersion > SEXPR_BOARD_FILE_VERSION );
|
||||
}
|
||||
|
||||
m_tooRecent = ( m_requiredVersion > SEXPR_BOARD_FILE_VERSION );
|
||||
|
||||
m_board->SetFileFormatVersionAtLoad( m_requiredVersion );
|
||||
}
|
||||
|
||||
|
@ -3866,6 +3893,16 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments
|
|||
CurSource(), CurLineNumber(), CurOffset() ) );
|
||||
}
|
||||
|
||||
auto checkVersion =
|
||||
[&]()
|
||||
{
|
||||
if( m_requiredVersion > SEXPR_BOARD_FILE_VERSION )
|
||||
{
|
||||
throw FUTURE_FORMAT_ERROR( fmt::format( "{}", m_requiredVersion ),
|
||||
m_generatorVersion );
|
||||
}
|
||||
};
|
||||
|
||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
{
|
||||
if( token == T_LEFT )
|
||||
|
@ -3893,6 +3930,19 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments
|
|||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_generator_version:
|
||||
{
|
||||
NeedSYMBOL();
|
||||
m_generatorVersion = FromUTF8();
|
||||
NeedRIGHT();
|
||||
|
||||
// If the format includes a generator version, by this point we have enough info to
|
||||
// do the version check here
|
||||
checkVersion();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case T_locked:
|
||||
footprint->SetLocked( true );
|
||||
break;
|
||||
|
|
|
@ -386,6 +386,7 @@ private:
|
|||
std::vector<int> m_netCodes; ///< net codes mapping for boards being loaded
|
||||
bool m_tooRecent; ///< true if version parses as later than supported
|
||||
int m_requiredVersion; ///< set to the KiCad format version this board requires
|
||||
wxString m_generatorVersion; ///< Set to the generator version this board requires
|
||||
bool m_appendToExisting; ///< reading into an existing board; reset UUIDs
|
||||
|
||||
///< if resetting UUIDs, record new ones to update groups with.
|
||||
|
|
Loading…
Reference in New Issue