Eeschema: fix UTF8 character handling bug in legacy parser.
Iterating over unquoted strings as ASCII8 fails when ' ' character is
not the LSB of a UTF8 string with wide characters. Change parsing method
for unquoted strings to convert the entire line as UTF8 and then use
wxStringTokenizer to break the line into tokens at the ' ' characters.
Fixes lp:1806206
https://bugs.launchpad.net/kicad/+bug/1806206
(cherry picked from commit a61a51f26e
)
This commit is contained in:
parent
4aeef1e09e
commit
61b94c8c2c
|
@ -2426,8 +2426,10 @@ void SCH_LEGACY_PLUGIN_CACHE::loadDocs()
|
||||||
if( !strCompare( "$CMP", line, &line ) != 0 )
|
if( !strCompare( "$CMP", line, &line ) != 0 )
|
||||||
SCH_PARSE_ERROR( "$CMP command expected", reader, line );
|
SCH_PARSE_ERROR( "$CMP command expected", reader, line );
|
||||||
|
|
||||||
parseUnquotedString( aliasName, reader, line, &line ); // Alias name.
|
aliasName = wxString::FromUTF8( line );
|
||||||
|
aliasName.Trim();
|
||||||
aliasName = LIB_ID::FixIllegalChars( aliasName, LIB_ID::ID_SCH );
|
aliasName = LIB_ID::FixIllegalChars( aliasName, LIB_ID::ID_SCH );
|
||||||
|
|
||||||
LIB_ALIAS_MAP::iterator it = m_aliases.find( aliasName );
|
LIB_ALIAS_MAP::iterator it = m_aliases.find( aliasName );
|
||||||
|
|
||||||
if( it == m_aliases.end() )
|
if( it == m_aliases.end() )
|
||||||
|
@ -2509,32 +2511,63 @@ LIB_PART* SCH_LEGACY_PLUGIN_CACHE::loadPart( FILE_LINE_READER& aReader )
|
||||||
|
|
||||||
wxCHECK( strCompare( "DEF", line, &line ), NULL );
|
wxCHECK( strCompare( "DEF", line, &line ), NULL );
|
||||||
|
|
||||||
// Read DEF line:
|
long num;
|
||||||
char yes_no = 0;
|
size_t pos = 4; // "DEF" plus the first space.
|
||||||
|
wxString utf8Line = wxString::FromUTF8( line );
|
||||||
|
wxStringTokenizer tokens( utf8Line, " \r\n\t" );
|
||||||
|
|
||||||
|
if( tokens.CountTokens() < 8 )
|
||||||
|
SCH_PARSE_ERROR( "invalid symbol definition", aReader, line );
|
||||||
|
|
||||||
|
// Read DEF line:
|
||||||
std::unique_ptr< LIB_PART > part( new LIB_PART( wxEmptyString ) );
|
std::unique_ptr< LIB_PART > part( new LIB_PART( wxEmptyString ) );
|
||||||
|
|
||||||
wxString name, prefix;
|
wxString name, prefix, tmp;
|
||||||
|
|
||||||
parseUnquotedString( name, aReader, line, &line ); // Part name.
|
name = tokens.GetNextToken();
|
||||||
parseUnquotedString( prefix, aReader, line, &line ); // Prefix name
|
pos += name.size() + 1;
|
||||||
parseInt( aReader, line, &line ); // NumOfPins, unused.
|
|
||||||
part->SetPinNameOffset( parseInt( aReader, line, &line ) ); // Pin name offset.
|
|
||||||
yes_no = parseChar( aReader, line, &line ); // Show pin numbers.
|
|
||||||
|
|
||||||
if( !( yes_no == 'Y' || yes_no == 'N') )
|
prefix = tokens.GetNextToken();
|
||||||
SCH_PARSE_ERROR( "expected Y or N", aReader, line );
|
pos += prefix.size() + 1;
|
||||||
|
|
||||||
part->SetShowPinNumbers( ( yes_no == 'N' ) ? false : true );
|
tmp = tokens.GetNextToken();
|
||||||
|
pos += tmp.size() + 1; // NumOfPins, unused.
|
||||||
|
|
||||||
yes_no = parseChar( aReader, line, &line ); // Show pin numbers.
|
tmp = tokens.GetNextToken(); // Pin name offset.
|
||||||
|
|
||||||
if( !( yes_no == 'Y' || yes_no == 'N') )
|
if( !tmp.ToLong( &num ) )
|
||||||
SCH_PARSE_ERROR( "expected Y or N", aReader, line );
|
THROW_PARSE_ERROR( "invalid pin offset", aReader.GetSource(), aReader.Line(),
|
||||||
|
aReader.LineNumber(), pos );
|
||||||
|
|
||||||
part->SetShowPinNames( ( yes_no == 'N' ) ? false : true ); // Show pin names.
|
pos += tmp.size() + 1;
|
||||||
|
part->SetPinNameOffset( (int)num );
|
||||||
|
|
||||||
part->SetUnitCount( parseInt( aReader, line, &line ) ); // Number of units.
|
tmp = tokens.GetNextToken(); // Show pin numbers.
|
||||||
|
|
||||||
|
if( !( tmp == "Y" || tmp == "N") )
|
||||||
|
THROW_PARSE_ERROR( "expected Y or N", aReader.GetSource(), aReader.Line(),
|
||||||
|
aReader.LineNumber(), pos );
|
||||||
|
|
||||||
|
pos += tmp.size() + 1;
|
||||||
|
part->SetShowPinNumbers( ( tmp == "N" ) ? false : true );
|
||||||
|
|
||||||
|
tmp = tokens.GetNextToken(); // Show pin names.
|
||||||
|
|
||||||
|
if( !( tmp == "Y" || tmp == "N") )
|
||||||
|
THROW_PARSE_ERROR( "expected Y or N", aReader.GetSource(), aReader.Line(),
|
||||||
|
aReader.LineNumber(), pos );
|
||||||
|
|
||||||
|
pos += tmp.size() + 1;
|
||||||
|
part->SetShowPinNames( ( tmp == "N" ) ? false : true );
|
||||||
|
|
||||||
|
tmp = tokens.GetNextToken(); // Number of units.
|
||||||
|
|
||||||
|
if( !tmp.ToLong( &num ) )
|
||||||
|
THROW_PARSE_ERROR( "invalid unit count", aReader.GetSource(), aReader.Line(),
|
||||||
|
aReader.LineNumber(), pos );
|
||||||
|
|
||||||
|
pos += tmp.size() + 1;
|
||||||
|
part->SetUnitCount( (int)num );
|
||||||
|
|
||||||
// Ensure m_unitCount is >= 1. Could be read as 0 in old libraries.
|
// Ensure m_unitCount is >= 1. Could be read as 0 in old libraries.
|
||||||
if( part->GetUnitCount() < 1 )
|
if( part->GetUnitCount() < 1 )
|
||||||
|
@ -2583,32 +2616,36 @@ LIB_PART* SCH_LEGACY_PLUGIN_CACHE::loadPart( FILE_LINE_READER& aReader )
|
||||||
{
|
{
|
||||||
// Nothing needs to be set since the default setting for symbols with multiple
|
// Nothing needs to be set since the default setting for symbols with multiple
|
||||||
// units were never interchangeable. Just parse the 0 an move on.
|
// units were never interchangeable. Just parse the 0 an move on.
|
||||||
parseInt( aReader, line, &line );
|
tmp = tokens.GetNextToken();
|
||||||
|
pos += tmp.size() + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char locked = parseChar( aReader, line, &line );
|
tmp = tokens.GetNextToken();
|
||||||
|
|
||||||
if( locked == 'L' )
|
if( tmp == "L" )
|
||||||
part->LockUnits( true );
|
part->LockUnits( true );
|
||||||
else if( locked == 'F' || locked == '0' )
|
else if( tmp == "F" || tmp == "0" )
|
||||||
part->LockUnits( false );
|
part->LockUnits( false );
|
||||||
else
|
else
|
||||||
SCH_PARSE_ERROR( "expected L, F, or 0", aReader, line );
|
THROW_PARSE_ERROR( "expected L, F, or 0", aReader.GetSource(), aReader.Line(),
|
||||||
|
aReader.LineNumber(), pos );
|
||||||
|
|
||||||
|
pos += tmp.size() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// There is the optional power component flag.
|
// There is the optional power component flag.
|
||||||
if( *line )
|
if( tokens.HasMoreTokens() )
|
||||||
{
|
{
|
||||||
char power = parseChar( aReader, line, &line );
|
tmp = tokens.GetNextToken();
|
||||||
|
|
||||||
if( power == 'P' )
|
if( tmp == "P" )
|
||||||
part->SetPower();
|
part->SetPower();
|
||||||
else if( power == 'N' )
|
else if( tmp == "N" )
|
||||||
part->SetNormal();
|
part->SetNormal();
|
||||||
else
|
else
|
||||||
SCH_PARSE_ERROR( "expected P or N", aReader, line );
|
THROW_PARSE_ERROR( "expected P or N", aReader.GetSource(), aReader.Line(),
|
||||||
|
aReader.LineNumber(), pos );
|
||||||
}
|
}
|
||||||
|
|
||||||
line = aReader.ReadLine();
|
line = aReader.ReadLine();
|
||||||
|
@ -2713,17 +2750,15 @@ void SCH_LEGACY_PLUGIN_CACHE::loadAliases( std::unique_ptr< LIB_PART >& aPart,
|
||||||
|
|
||||||
wxCHECK_RET( strCompare( "ALIAS", line, &line ), "Invalid ALIAS section" );
|
wxCHECK_RET( strCompare( "ALIAS", line, &line ), "Invalid ALIAS section" );
|
||||||
|
|
||||||
// Parse the ALIAS list.
|
wxString utf8Line = wxString::FromUTF8( line );
|
||||||
wxString alias;
|
wxStringTokenizer tokens( utf8Line, " \r\n\t" );
|
||||||
parseUnquotedString( alias, aReader, line, &line );
|
|
||||||
|
|
||||||
while( !alias.IsEmpty() )
|
// Parse the ALIAS list.
|
||||||
|
while( tokens.HasMoreTokens() )
|
||||||
{
|
{
|
||||||
newAlias = alias;
|
newAlias = tokens.GetNextToken();
|
||||||
checkForDuplicates( newAlias );
|
checkForDuplicates( newAlias );
|
||||||
aPart->AddAlias( newAlias );
|
aPart->AddAlias( newAlias );
|
||||||
alias.clear();
|
|
||||||
parseUnquotedString( alias, aReader, line, &line, true );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue